LINUX.ORG.RU

В Си макро магии для строк подвезли

 , ,


2

3

https://github.com/skullchap/chadstr

int table = 13;
int id = 37; 
str test1 = str("SELECT * FROM ", table, " where person_id ", id);
str test2 = str(test1);         //copies test1 to test2
str test3 = str(test2, test1); // returns concat of test2 and test1

test2 = test1; // acceptable, but wrong since test2 now points to test1 not copies it.

str(*test1); // returns const char* to use in printf like functions
Ex: puts(str(*test1)); // prints test1
chadstr test1 = str("pineapple"); 
chadstr test1range = str((range)(test1, 3,6)); // neap

Судя по всему оно умеет интерполяцию строк (в тч и конкатенацию) а так же виртуальные ранжи. В исходном коде есть зачатки сборщика мусора.

Исходный код с кучей макро магии https://github.com/skullchap/chadstr/blob/master/chadstr.h.

★★★★

Ответ на: комментарий от menangen

Я не путаю.

Я знаю.

И, честно говоря, ждал именно этого ответа. Просто потому, что в таком случае (если для многопоточного программирования используются каналы), то Go-программисты ещё бестолковее чем даже можно было представить.

Вообще-то, если мне нужна именно многопоточная программа, то для обмена данными между потоками у меня средств выше крыши. Понимаю что не-С программистам сложно это прочесть, усвоить и понять, но факт остаётся фактом. Авторы Go слишком бестолковы, чтобы понимать что и зачем они делают, т.к. они даже не представляют себе как именно эти задачи уже были решены до них. Теперь они по своей дури считают что средства для межпроцессного взаимодействия нужно применять в многопоточных программах? =))) Да как же и стандартными для многопоточных программ средствами обходятся-то? =)))

Предлагаете «изучать» как авторы Go там нарукоблудили? Новое направление в творчестве идиотов? Не, я пас. Спасибо.

Посмотри libmill http://libmill.org

Умоляю! =))) Вы в следующий раз просто аккуратнее, а то я взоржахом аки конь стоялый. Всю семью перебудил… =)))

Вот в Вашем примере автору этой либы вовремя просто не сказали – «Прочти буквари, дятел». В результате он нарукоблудил (зачем-то!) какую-то очередную херню, абсолютно не зная о том, что сама по себе концепция coroutines была изложена в Dahl, O.-J., Dijkstra, E. W., and Hoare, C. A. R. 1972. Hierarchical program structures. In Structured Programming, Second ed. Academic Press, London, England. В 1972г., уточню ещё раз. И это ни хрена ни как не относится к Go, которого тогда и в госплане не было.

Первая и самая, пожалуй, известная и удачная реализация относится к 2000г. by Simon Tatham.

С тех пор воды утекло аж море. Решений есть полно. Например. Ещё пример, ещё, и ещё.

Т.е., coroutines в С это как минимум, не новость. Но вот идиот, автор libmill о них почему-то ничего не знает. Он скодерасил какую-то говнину чтобы был «Go-style»… Ай, маладэс! Как же без него раньше-то, аж с 2000-го года, вот уже 20 лет мы живём-то… =)))

Теперь вот вопрос – как перестать орать и бугагировать… Go-style чуваку понадобился… Бггг… =)))

Moisha_Liberman ★★
()
Последнее исправление: Moisha_Liberman (всего исправлений: 1)
Ответ на: Я не путаю. от Moisha_Liberman

Так, истерику в сторону, а что по поводу многопоточных coroutines? И средств не синхронизации, а коммуникации между ними? В го то эти горутины работают на разных ядрах, а в си как это сделать?

menangen ★★★★★
()
Последнее исправление: menangen (всего исправлений: 1)
Ответ на: Я не путаю. от Moisha_Liberman

для обмена данными между потоками у меня средств выше крыши

Например? И сколько из них популярны и используются в продакшен?

menangen ★★★★★
()
Ответ на: Я не путаю. от Moisha_Liberman
https://github.com/sustrik/libmill/                        Go-style concurrency in C

http://libmill.org/download.html

https://github.com/sustrik/libdill                         Structured concurrency in C
                                                           https://travis-ci.org/sustrik/libdill

https://250bpm.com/

https://nanomsg.org/download.html

https://github.com/nanomsg/nanomsg/                        The nanomsg library is a simple high-performance implementation of several "scalability protocols".
                                                           These scalability protocols are light-weight messaging protocols which can be used to solve a number of very common messaging patterns, such as request/reply, 
                                                           publish/subscribe, surveyor/respondent, and so forth. 
                                                           These protocols can run over a variety of transports such as TCP, UNIX sockets, and even WebSocket.

https://nanomsg.org/documentation.html

https://github.com/achille-roussel/nanomsgxx               Nanomsg binding for C++11

https://github.com/achille-roussel/go-dl                   Go bindings to libdl

https://github.com/achille-roussel/mpack-c                 C implementation of MessagePack encoder and decoder.

https://github.com/achille-roussel/go-ffi                  Go bindings to libffi

https://github.com/achille-roussel/mpack-js                Javascript implementation of MessagePack encoder and decoder.

http://hackage.haskell.org/package/nanomsg-haskell         This is a Haskell binding for the nanomsg library: http://nanomsg.org/.

https://nanomsg.org/documentation.html                     Documentation links
Vladimirmir
()
Ответ на: Хммм... от Moisha_Liberman

Видимо, Go-программисты… не умеют читать и добавляют то, о чём изначально не имеют понятия?

Да да поучи одного из создателей юникса Кена Томпсона как пользоваться пиписами.

anonymous
()
Ответ на: комментарий от menangen

а что по поводу многопоточных coroutines?

А с каких пор корутины стали многопоточными?

И средств не синхронизации, а коммуникации между ними?

т.е. мьютексов, CV, атомиков тебе не хватает?

а в си как это сделать?

Ты потоки запускать не умеешь?

anonymous
()
Ответ на: комментарий от Ford_Focus

какое кому дело до их личного локального самодурства

anonymous
()
Ответ на: комментарий от anonymous

купи уже норм проц

Расту никакой процессор не поможет, только вычислительный кластер.

X512 ★★★★★
()
Ответ на: комментарий от shleemypants

Да я тоже...

малиновый смузи люблю похлебать. Иной раз. Чё бы нет-то?

И тут я чуть смузи не подавился…

Ну Вы уж там аккуратнее как-нибудь, право! =)))

Moisha_Liberman ★★
()
Ответ на: комментарий от menangen

Хорошо.

истерику в сторону,

Утерев скупую мужскую слезу от хохота, которая катилась по моей небритой щеке, продолжим. =)))

а что по поводу многопоточных coroutines?

Каких это «многопоточных coroutines»? Откуда бы они стали многопоточными-то? Это в С я из потока могу ещё потоков понасоздавать при необходимости. Получится «матрёшка», но да и хрен бы с ним пока потоки остаются управляемыми (об этом будет ниже). Так что, что там с coroutines я и не знаю и знать не хочу.

В дальнейшем я предполагаю что Вы задали вопрос не про coroutines, а про pthreads, т.е. про потоки исполнения. Т.к. coroutines это и есть слабенький аналог потоков.

И средств не синхронизации, а коммуникации между ними?

Вообще-то, в корне неверно. Здесь может быть два ответа – либо средств коммуникации между потоками может быть всего одно, либо их может быть несколько. Тут всё зависит от того, как посмотреть.

Для многопоточных приложений нужно помнить что у процесса есть единое адресное пространство. И здесь не зависит сколько у нас потоков исполнения в процессе и на каких ядрах они запущены (про ядра тоже будет ниже). Попросту если, то Вам даже ничего не нужно вымудрять отдельного для передачи данных от потока к потоку внутри одного процесса. Можете просто либо по ссылке, либо по значению передавать и не создавать ни каких «каналов», «пайпов». Считайте что данные внутри потока для любого процесса могут быть просто переменными. Поэтому здесь и есть ответ – решение для передачи данным внутри процесса всегда одно.

Но тогда возникает проблема, связанная с тем, что у Вас в этом случае в общем адресном пространстве процесса начнётся полный п-ц (одни проблемы с race conditions чего стоят). Чтобы его (п-ц) не допустить, и нужны эти самые методы синхронизации потоков. Это те же pthread_barrier, мьютексы, семафоры и т.д. и т.п. Поэтому здесь справедлив и второй ответ – методов передачи данных между потоками одного процесса выше крыши. Т.е., много. Потому что отделять общую память процесса от методов синхронизации нельзя. Одно без другого не работает.

И сколько из них популярны и используются в продакшен?

Все, о которых знает С-программист. Использование того или иного механизма синхронизации потоков целиком и полностью зависит от программиста и стоящей перед ним задачи. Насколько он хорошо матчасть освоил. Если он в принципе не понимает что все данные хранятся в общем адресном пространстве процесса и зачем тут синхронизация потоков, то всё плохо.

В Go же, как мы видим, пошли своим неизведанным путём – взяли средства синхронизации между процессами и вхреначили их как метод синхронизации и обмена данными между потоками, которыми coroutines и являются по своей сути. Вот в чём дело-то и что именно вызывает дикий ржач. =))) Потери производительности? Не, не слышали.

В го то эти горутины работают на разных ядрах, а в си как это сделать?

В С в 99.9(9) процентах случаев Вам не надо даже об этом голову ломать. Системный планировщик работает и балансирует нагрузку между ядрами сам, без Вашего участия, при необходимости перекидывая поток или процесс с одного ядра на менее загруженные. А может и вообще этого не делать – ему виднее. Так что, на каком там ядре работает Ваш поток, это вообще пофигу.

Единственный момент – я в С могу прибить к ядру процессора гвоздиками свой поток исполнения. Т.е., запустил процесс и отправил на одно из ядер процессора свой отдельный поток (один из вариантов, прямо спецом для потоков вот – pthread_attr_setaffinity_np()). Тем самым я вообще посылаю на хрен системный планировщик с его «пожеланиями» и мой поток работает на отдельном ядре процессора.

Зачем это надо? Ну, чтобы например считать какую-нибудь крипту постоянно. Данные для расчёта попали в кеш процессора, а дальше мы просто считаем и используем данные из кеша, максимально в него попадая и тем самым, ускоряя расчёт. Ну или если мне надо чтобы какой-то поток постоянно «обмолачивал» файлы в процессе работы и делал бы это как можно быстрее. Всё-таки, планировщик, перенося поток между ядрами на нагруженном процессоре, может ухудшить ситуацию, а не улучшить её.

Скажите – а в Go я могу вынести отдельные coroutines на конкретные ядра процессора?

Moisha_Liberman ★★
()
Ответ на: комментарий от anonymous

Чем-чем? =)))

Да да поучи одного из создателей юникса Кена Томпсона как пользоваться пиписами.

Прочитав «пиписами» (ну хотя бы «пайпсами» написали бы) я много думал… Чем же там Кен Томпсон пользовался так мастерски и при чём тут Go-программисты. Нешто он их породил? Своим пиписом? =)))

Однако, когда до меня дошло что именно Вы хотели сказать, то я понял что Вы не вкуриваете того факта, что к pthreads, аналогом которых являются coroutines, pipes не имеют никакого отношения. Pipes имеют отношение к processes. Разные вещи вообще-то…

Так что, Ваша отсылка к авторитету господина Томпсона, не имеет ничего общего с реалиями. Go, к стати, тоже как мы все видим.

Moisha_Liberman ★★
()
Последнее исправление: Moisha_Liberman (всего исправлений: 1)
Ответ на: Хорошо. от Moisha_Liberman

Управляемость.

Это отдельный момент, т.к. нужна не только быстрая, но ещё и управляемая реализация.

Да, говорят что coroutines порождаются быстрее чем pthreads. Про processes и не говорим – те вообще тормоза. Но нафига мне быстрота порождения потоков, если я запустил процесс-демон, из него разово породил все нужные потоки и потом они просто и тупо работают? В этом случае система (точнее, системный планировщик ядра) видит все процессы и потоки и может нагружать процессор так, чтобы были задействованы по максимуму все ядра. Ну, конечно, если я по-другому не решу.

Если мне в принципе наплевать на этот момент, то я могу вообще использовать green threads. Самая «широко распространённая» библиотека для этого (на деле, их довольно много, но я пользуюсь этим) – GNU Pth. Это non-preemptive реализация псевдо-потоков, у которой API весьма похож на стандартные pthreads. Т.е., это весьма быстро порождаемые потоки, про которые система вообще ничего не знает, они извне моего процесса или потока не видны вовсе. Тут я сам должен разруливать планирование исполнения. Странно, но эта либа родилась году этак в 1999, я с нею дружу с начала 2000-х. Т.е., у меня всё что мне нужно есть, под разные задачи.

К чему это я всё? Да к тому, что в С уже при всей его простоте столько напридумывали, что даже множество всех решений прикинуть даже сложно. Но нет, мы же хотим новых, неизведанных грабель, на которые не ступала нога программиста! Давайте новый язык придумаем! =)))

Moisha_Liberman ★★
()
Ответ на: комментарий от MOPKOBKA

Если в го они собираются так как ты хочешь, то почему в Си это не реально?)

menangen ★★★★★
()
Ответ на: Управляемость. от Moisha_Liberman

я русский и православный

Знатно ты поделил на ноль, жидёнок яхвистский.

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

Сгорите вместе со своими крестатыми синагогами.

anonymous
()
Ответ на: комментарий от menangen

Ну так а зачем ты назвал эту поделку корутинами? Воткнули вместо системного планировщика собственный, но это вообще другое. Видимо иначе вы бы там не поосиливали, ещё и каналы для самых маленьких всунули. И вот это всё ты в Си предлагаешь?) Не, спасибо. В плюсах корутины без всяких планировщиков сделали.

anonymous
()
Ответ на: Хорошо. от Moisha_Liberman

Не знаю, я на го не пишу, можно ли там прибить на одно ядро горутину, она и так будет на одном ядре крутиться, если на каком-то конкретном именно - не факт, да и нужно ли это

menangen ★★★★★
()
Ответ на: Хорошо. от Moisha_Liberman

Ты там что описал - это всё туфта с расшариванием общей памяти между потоками - старое ненужно говно, посмотри как в GCD / libdispatch это делают белые люди, а не мучаются с твоей расшаренной памятью как в 90-ые, это ж надо настолько любить жрать кактус…

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

menangen ★★★★★
()
Ответ на: комментарий от anonymous

Может потому, что они сами назвали их корутинами? Только по приколу поменяли одну первую букву, чтобы было понятно, что это корутины для Go рантайм и они многопоточны? Что Си сасай, и у них нет вменяемых абстракций для многопоточного программирования?

menangen ★★★★★
()
Последнее исправление: menangen (всего исправлений: 2)
Ответ на: комментарий от menangen

Они их не называли корутинами, это ты тут начал многопоточные сказки рассказывать. До корутин это дерьмо не дотянуло, вот и пришлось букву менять. А вообще, все эти корутины делаются школьником из палок за 5 минут.

anonymous
()

Си и Си-подобные языки (особенно - кресты) созданы для эксплуатации программистов корпорациями. Писать приложения на сях - это участвовать в тестинге фич нужных корпорациям. Там же используются заголовки, в которые релизеры вливают что хотят. Вообще С и C++ всасывают пылесосом всё говно из системы. Нужно очень постараться, чтобы не дать им всосать говно в код.

А вот Паскаль был придуман для людей. Последующие языки же были придуманы из желания его искалечить и при этом сделать работоспособными. Вина всяких преподов на Паскале в том, что они предавали как с помощью ЯП заниматься отвлечённой фигнёй, а не как на них писать полезные программы и не натыкаться на грабли реализаций компиляторов и железа. Банально паузу ставить в показательных циклах не учили - пусть проц погреется!

Вот и пришли к засилью сишного ужаса везде. И с каждым днем все больше костылей. Выходит новая версия какой-то плюсовой нерепозиторной программы. Ты такой включаешь клиент, сщас во что-нибудь поиграю, а тут клиент - хрясь! И по интернету самобновился. После этого мало того что требует отсутствующих в системе либ, так ему ещё и линкер имеющий звиздецовые зависимости вынь, да положь.

Kinlipan
()

Вот ещё что в С/С++ доставляет - так это стандарты. То есть какая-то закрытая группа «сионских мудрецов» собирается где-то на сходку и решает что во всём мире во всех компиляторах этих языков должно быть, а недопрограммисты-пейсатели пусть это используют и о нужных им фичах и не мечтают - за них мудрецы придумают когда надо будет...

Kinlipan
()
Ответ на: комментарий от menangen

Огггадааа... =)))

Точно-точно! =)))

можно ли там прибить на одно ядро горутину, она и так будет на одном ядре крутиться, если на каком-то конкретном именно - не факт, да и нужно ли это

Т.е., другими словами – можем ли мы запилить такую фичу как в С я не знаю, но если нет, то поверьте – оно вам ненужно. Угу, понятно… Так бы сразу и сказали… =)))

Нет. Оно нам нужно и те кому нужно, явно в курсе зачем. Избежать cache misses это дорогого стоит.

Что Си сасай, и у них нет вменяемых абстракций для многопоточного программирования?

Вообще-то, я ожидал раньше, но этого так ни кто и не сделал, так что придётся самому. =)))

А что, для Вас это сюрприз что в С нет многопоточного программирования? Ну, по крайней мере, до С11 не было (аккуратно, PDF), да и в самом по себе С11 оно там не очень? Уж по крайней мере не так развито как те же POSIX pthreads (у того же M.Kerrisk в его книге The Linux Programming Interface аж пять глав про threads), хотя базовую функциональность обеспечивает.

Вообще-то, всё что мы обсуждали выше про POSIX pthreads это обсуждение API системы, а не стандарта языка. На языке, в котором «нет абстракций для многопоточного программирования» запилили как минимум три реализации для многопоточного программирования – сами по себе POSIX pthreads, WIN32 threads и сюда же можно отнести GLib, где поддержка многопоточности типа «своя».

Странно, да? Поддержки многопоточности нет, а сама многопоточность есть… =)))

Может потому, что они сами назвали их корутинами?

Ну, скажем так, с дуру можно и член сломать. Причём, в трёх местах сразу… Чё бы не назвать coroutines? В особенности, учитывая что в 1972г. такое название уже мелькало… =)))

а не мучаются с твоей расшаренной памятью как в 90-ые, это ж надо настолько любить жрать кактус…

Кто мучается? Зачем мучаться, если в пределах процесса память и так расшарена для его потков-потомков? На хрен тут вымудрять какие-то атсракции на ровном месте?

«Мой папаша был ремонтником, так вот он говаривал – если работает – не чини…» (c) к/ф «Солдат».

Хотя, если совсем уж заняться нечем, то чтобы не лизать яйца, можно и новый язычёк, со старыми-новыми абстракциями придумать. =)))

Moisha_Liberman ★★
()
Последнее исправление: Moisha_Liberman (всего исправлений: 2)
Ответ на: комментарий от X512

И исключения нормальные до сих пор не завезли.

Нормальных исключений не бывает. Хотите чтобы «выглядело изящно» ~ занимайтесь математикой, а в программировании нужно чтобы легко было понять где произошла ошибка и каков её контекст. Иксепшоны удовлетворительно решают только первую часть вопроса, а решение второй получается намного тяжелее чем обработка ошибок как значений. Сравнение:

file := os.open("file.txt") or err {
    return err.wrap("<кантекст>")
}

против

os::File file;
try {
    file = os::open("file.txt")
} except (std::exception &e) {
    throw e.wrap("<кантекст>")
}

не, но конечно можно всю запихнуть в один блок, только тогда будет получаться как у моих коллег пишущих на плюсах, когда тостеры вынуждены кучу времени тратить им на помощь вместо того чтобы заниматься своими первоочередными обязанностями: «а щас ещё раз попробуй запустить», тьфу, клоунада.

Joe_Bishop
()
Ответ на: комментарий от Joe_Bishop

Нормальных исключений не бывает. Хотите чтобы «выглядело изящно» ~ занимайтесь математикой, а в программировании нужно чтобы легко было понять где произошла ошибка и каков её контекст.

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

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от Joe_Bishop

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

Ну а про core dump ты ничего не слышал конечно же? Если исключение перехватываешь, то знаешь что делаешь, если нет, то получаешь полнейшую инфу о контексте вплоть до значения переменных. В общем случае все стандартные исключения не для перехвата, программа должна завалиться и скинуть корку. Если после исключения нужно продолжить выполнение, то выбрасывается некоторый собственный тип, очевидно, что в таком случае контекст понятет.

pavlick ★★
()
Ответ на: комментарий от Eddy_Em

Начал читать новость с мыслью «Ну щас Эдик возбудится и будет кричать «си сломали, не нужно!», а потом увидел твой коммент самым первым :)

Zhbert ★★★★★
()
Ответ на: комментарий от Joe_Bishop

решение второй получается намного тяжелее чем обработка ошибок как значений. Сравнение:

но конечно можно всю запихнуть в один блок, только тогда будет получаться как у моих коллег пишущих на плюсах

И похоже ты один из тех, кто не монимает разницы между исключениями и ошибками, когда надо юзать первое, а когда второе. Коллеги тоже супер ))

pavlick ★★
()
Ответ на: комментарий от pavlick

И похоже ты один из тех, кто не монимает разницы между исключениями и ошибками, когда надо юзать первое, а когда второе. Коллеги тоже супер ))

Побольше смайликов поставь, ещё смешнее будет. В говноязыках Джяба/Кресты/Сисярп/Далее идиоматическая обработка ошибок построена на исключениях. Если ты для себя их разделяешь, то это скорее уже твои проблемы и пахнет чистым говнокодерством: нормальный программист пишет понятные для других программы.

Joe_Bishop
()
Последнее исправление: Joe_Bishop (всего исправлений: 1)
Ответ на: комментарий от bga_

Значит это дерьмо, а не язык. Можно было сразу нормальный компилятор написать.

Hertz ★★★★★
()
Ответ на: комментарий от Eddy_Em

Как говорил один мой знакомый профессор с мехмата: «Всякие бывают на свете чудеса»

Benis
()
22 июля 2021 г.
Ответ на: комментарий от anonymous

Для реализации...

Подскажите пожалуйства, как и для чего Вы используете green threads ?

Конечно же для реализации некоего «мелкого» обмена в сети. Когда нет шансов что обрабатываемый запрос будет очень долго исполняться. Например (именно «например») к такого рода случаям можно отнести запрос данных с какого-либо датчика, привязанного к данному компу локально. Т.е., когда пришёл запрос, я обратился к уже открытому дескриптору, прочёл оттуда данные, вернул их в ответ на запрос. Когда нет вариантов, когда у меня будут сложности с запросом и его отработка займёт доли секунды.

Например, запросы, обрабатываемые в собственном ntp-сервере я так и реализовал. Здесь green threads хороши. Мутить отдельный поток я тут смысла не вижу.

Moisha_Liberman ★★
()
Ответ на: комментарий от LongLiveUbuntu

Вот можешь почитать что УЖЕ принято: http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2391r0.pdf (всего 2 странички, очень кратко там всё)

Я верю в комитет С, и что все «Unadopted Features Being Explored» будут приняты к релизу…

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.