Re: а попинайте либу
От: Abyx Россия  
Дата: 13.12.13 18:10
Оценка: +2 -4
Здравствуйте, cyberzlodey, Вы писали:

C>libaoc

C> Запилил на досуге простую библиотечку на мотив паттерна Active object на голом С. Какие комментарии по коду, архитектуре, стилю программирования? Буду рад конструктивному фидбеку. Спасибо.

Си не нужен. ты бы еще на брейнфаке запилил.
In Zen We Trust
Re[2]: а попинайте либу
От: cyberzlodey  
Дата: 13.12.13 18:27
Оценка: +3 :))
Здравствуйте, Abyx, Вы писали:


A>Си не нужен. ты бы еще на брейнфаке запилил.


Спасибо, ваш комментарий очень важен для меня
Re[7]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 12:52
Оценка: -2 :)
а это как понимать?
вот я зарукоблудил такой код:
blocking_queue_t *q = 0;
blocking_queue_destroy(&q);

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

т.е. в идеальном случае, код использования этой библиотеки должен быть таким:
active_t *a = 0;
int ec = active_new(&a);
if ( ec ) {
   printf(stderr, "initialization error, errno=%d\n", ec);
   return ec;
}

blocking_queue_t *q = blocking_queue_new(a);
if ( !q ) {
   ec = active_errno(a);
   printf(stderr, "error creating blocking_queue object, errno=%d\n", ec);

   active_destroy(&a);
   return ec;
}

...
...

blocking_queue_destroy(&q);
active_destroy(&a);



я пытаюсь обратить твое внимание на нелогичности.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[5]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 12:03
Оценка: -2
Здравствуйте, cyberzlodey, Вы писали:

C>Привычка, но в данном случае ничего криминального в постфиксном инкременте/декременте не вижу, поскольку применяется к целочисленным типам и накладные расходы на возвращение старого значения переменной едва ли будут заметны. Это же на С++ и инкрементируются не объекты с перегруженными оператороми инкремента

разница есть, ибо в префиксной форме создается дополнительная временная переменная.


вообще — там еще пилить и пилить =)

к примеру, используя 'active_t* active_new(void)' — как я узнаю по какой причине мне вернули NULL?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[7]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 12:30
Оценка: -1 :)
Здравствуйте, cyberzlodey, Вы писали:

C>проверить errno?

ты прикалываешься?

к примеру, при фэйле этой проверки, что мне скажет errno?

посмотри на примеры проектирования библиотек. там, есть два способа: 1)функция каким-либо образом сообщает пользователю кода о причине ошибке, 2)библиотека имеет переменную в глобальном контексте, в которую сохраняется errno. и, соответственно, библиотека предоставляет функцию для получения этого errno, типа: 'int active_errno(active_t*)'
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 05:32
Оценка: 1 (1)
Здравствуйте, cyberzlodey, Вы писали:

думаю, было бы неплохо функциям библиотеки присвоить префикс 'aoc_'. т.к. я начала читать примеры, и, признаюсь, не зная внутренностей библиотеки, сложно понять какая функция является библиотечным API, а какая частью теста.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[10]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:41
Оценка: -1
по поводу логирования библиотеки можно сделать так:
в объект сессии добавить член errstream, который по умолчанию, при создании сессии, будет инициализоваться либо stdout, либо stderr.
так же, добавить API типа 'aoc_set_error_stream(FILE*)' и 'FILE* aoc_get_error_stream()'
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[9]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:47
Оценка: -1
C>Вероятно логичным бы было действительно взвести какой-то внутренний флаг ошибки и получить через aoc_errno()?
кстати, если твоя библиотека сессионная — то у каждой сессии может быть свой errno. значит сигнатура должна быть такой: 'int aoc_errno(active_t*)'
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[11]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 14:18
Оценка: :)
как дополнение, можно добавить еще функцию возвращающую строковое представление ошибки, типа: 'const char* aoc_errorstr()'. еще, было бы не лишним чтоб эта же функция могла использоваться как для стандартных системных ошибок, так и для ошибок самой библиотеки. т.е. к примеру если не удалось выделить память, то при помощи 'int aoc_error()' мы получаем ENOMEM, а при помощи 'const char* aoc_errorstr()' получаем то, что возвращает strerror() для стандартных ошибок, и твое собственное сообщение для нестандартных.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: а попинайте либу
От: BulatZiganshin  
Дата: 13.10.14 16:54
Оценка: +1
Здравствуйте, cyberzlodey, Вы писали:

C>libaoc

C> Запилил на досуге простую библиотечку на мотив паттерна Active object на голом С. Какие комментарии по коду, архитектуре, стилю программирования? Буду рад конструктивному фидбеку. Спасибо.

взять готовую многопоточность из tiny threads. тогда получится тонкая надстройка над ним вместо дублирования его кода
Люди, я люблю вас! Будьте бдительны!!!
Re[13]: а попинайте либу
От: vdimas Россия  
Дата: 05.05.15 21:07
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>вы забыли отметить, что это всего лишь ваше мнение, одно из многих


Это не "мнение", это железное правило, принятое на сегодня везде в реально работающих АПИ, потому что альтернативные решения ошибочны. Моё мнение тут не при чем, "альтернативные" системы, действительно, работают с ошибками, вызванными банальными гонками, т.е. чаще всего банально писаны неопытными разработчиками.

В условиях требований реентерабельности некоего АПИ код ошибки должен либо возвращаться самой операцией, либо для его промежуточного хранения должен быть использован приватный слот потока. ОК, я не настаиваю конкретно на механизме errno, но на идентичной errno технике, если требуется брать ошибку последней операции ВНЕ контекста этой операции, — настаиваю. Потому что единственный контекст, который у нас остаётся в упомянутом сценарии — это контекст потока.
а попинайте либу
От: cyberzlodey  
Дата: 13.12.13 18:02
Оценка:
libaoc
Запилил на досуге простую библиотечку на мотив паттерна Active object на голом С. Какие комментарии по коду, архитектуре, стилю программирования? Буду рад конструктивному фидбеку. Спасибо.
Re[3]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 05:38
Оценка:
везде используется постфиксная форма инкремента(предположу, что и декремента). почему?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: а попинайте либу
От: cyberzlodey  
Дата: 15.12.13 06:39
Оценка:
Здравствуйте, niXman, Вы писали:

X>везде используется постфиксная форма инкремента(предположу, что и декремента). почему?


Привычка, но в данном случае ничего криминального в постфиксном инкременте/декременте не вижу, поскольку применяется к целочисленным типам и накладные расходы на возвращение старого значения переменной едва ли будут заметны. Это же на С++ и инкрементируются не объекты с перегруженными оператороми инкремента
Re[6]: а попинайте либу
От: cyberzlodey  
Дата: 15.12.13 12:20
Оценка:
Здравствуйте, niXman, Вы писали:


X>вообще — там еще пилить и пилить =)


с этим согласен

X>к примеру, используя 'active_t* active_new(void)' — как я узнаю по какой причине мне вернули NULL?


проверить errno?
Re[8]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:01
Оценка:
ну и я бы порекомендовал поверх ассерта заюзать макронадстройку, чтоб сделать его управляемым.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:03
Оценка:
Здравствуйте, niXman, Вы писали:

X>разница есть, ибо в префиксной форме создается дополнительная временная переменная.

*в постфиксной
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[8]: а попинайте либу
От: cyberzlodey  
Дата: 15.12.13 13:05
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, cyberzlodey, Вы писали:


C>>проверить errno?

X>ты прикалываешься?

X>к примеру, при фэйле этой проверки, что мне скажет errno?


Скажет ENOMEM, поскольку там только память под объект потока выделяется и ничего более.

X>посмотри на примеры проектирования библиотек. там, есть два способа: 1)функция каким-либо образом сообщает пользователю кода о причине ошибке, 2)библиотека имеет переменную в глобальном контексте, в которую сохраняется errno. и, соответственно, библиотека предоставляет функцию для получения этого errno, типа: 'int active_errno(active_t*)'


Ок, посоветуй какие конкретно библиотеки посмотреть. Глядя, например, на czmq — там подобного кода полно. Например вот. Хотя согласен там можно спросить у базовой библиотеки zmq_errno().
Re[8]: а попинайте либу
От: cyberzlodey  
Дата: 15.12.13 13:12
Оценка:
Здравствуйте, niXman, Вы писали:

X>а это как понимать?

X>вот я зарукоблудил такой код:
X>
X>blocking_queue_t *q = 0;
X>blocking_queue_destroy(&q);
X>

X>и рассчитываю что библиотека мне скажет что я идиот, ибо вызывать destroy для не созданного объекта — глупо. но библиотека ничего не скажет, ибо не содержит корректной проверки.

теоретически у клиента могут быть закрыты stderr, stdout, а для логгирования используются свои механизмы. Вероятно логичным бы было действительно взвести какой-то внутренний флаг ошибки и получить через aoc_errno()?

X>т.е. в идеальном случае, код использования этой библиотеки должен быть таким:

X>
X>active_t *a = 0;
X>int ec = active_new(&a);
X>if ( ec ) {
X>   printf(stderr, "initialization error, errno=%d\n", ec);
X>   return ec;
X>}

X>blocking_queue_t *q = blocking_queue_new(a);
X>if ( !q ) {
X>   ec = active_errno(a);
X>   printf(stderr, "error creating blocking_queue object, errno=%d\n", ec);

X>   active_destroy(&a);
X>   return ec;
X>}

X>...
X>...

X>blocking_queue_destroy(&q);
X>active_destroy(&a);
X>



X>я пытаюсь обратить твое внимание на нелогичности.


понимаю, спасибо
Re[9]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:27
Оценка:
Здравствуйте, cyberzlodey, Вы писали:

C>Скажет ENOMEM, поскольку там только память под объект потока выделяется и ничего более.

в errno этого не будет, потому что последующий вызов blocking_queue_destroy() затрет errno.

C>Ок, посоветуй какие конкретно библиотеки посмотреть.

curl

C>Глядя, например, на czmq — там подобного кода полно. Например вот. Хотя согласен там можно спросить у базовой библиотеки zmq_errno().

тут, похоже та же ошибка, ибо последующий вызов zctx__socket_destroy() может затереть errno.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[9]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 15.12.13 13:35
Оценка:
Здравствуйте, cyberzlodey, Вы писали:

C>теоретически у клиента могут быть закрыты stderr, stdout

stderr и stdout сами по себе закрытыми не бывают и не закрываются. так что то, что они по какой-то причине закрыты — это целиком головняк пользователя, а не библиотеки.

C>а для логгирования используются свои механизмы.

это вообще второе.

C>Вероятно логичным бы было действительно взвести какой-то внутренний флаг ошибки и получить через aoc_errno()?

да.
ты должен решить, какая сущность у тебя является обязательной, и без которой библиотека неспособна работать. я предположу, что это — active_t
в таком случае, тебе нужно ввести правило которое будет требовать, чтоб объект этого типа создавался первым и разрушался последним.

но тут возникает несколько вопросов:
1. эта библиотека сессионная?
2. должны ли API этой библиотеки привязываться к конкретной сессии?

ответ на первый вопрос даст пищу для размышления.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[10]: а попинайте либу
От: cyberzlodey  
Дата: 15.12.13 14:03
Оценка:
Здравствуйте, niXman, Вы писали:

X>кстати, если твоя библиотека сессионная — то у каждой сессии может быть свой errno. значит сигнатура должна быть такой: 'int aoc_errno(active_t*)'


Да, active_t объектов может быть множество, соответственно обработка ошибок должна привязываться к конкретному объекту. Спасибо за мысль, так и сделаю.
Re[8]: а попинайте либу
От: vdimas Россия  
Дата: 13.04.15 15:17
Оценка:
Здравствуйте, niXman, Вы писали:

X>библиотека имеет переменную в глобальном контексте, в которую сохраняется errno.


Никогда не давай таких советов.


X>и, соответственно, библиотека предоставляет функцию для получения этого errno, типа: 'int active_errno(active_t*)'


Бредовый дизайн, не в духе С, а в духе "поколения next", за которыми приходится постоянно подчищать.
Re[8]: а попинайте либу
От: vdimas Россия  
Дата: 13.04.15 15:25
Оценка:
Здравствуйте, niXman, Вы писали:

X>т.е. в идеальном случае, код использования этой библиотеки должен быть таким:

X>
X>active_t *a = 0;
X>int ec = active_new(&a);
X>if ( ec ) {
X>   printf(stderr, "initialization error, errno=%d\n", ec);
X>   return ec;
X>}


Не должен. Этот подход не позволит воспользоваться некоей уже имеющейся прикладной инфраструктурой вокруг errno.

Вот классика жанра:
sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd == INVALID_SOCKET) {
  notifyError("ERROR opening socket");
  return;
}


notifyError неявно использует errno, который, в отличие от самописных глобальных аналогов, свой у каждого потока.


X>я пытаюсь обратить твое внимание на нелогичности.


Ты пытаешься задурить голову непонятно чем. Ты даже не обосновал, ЗАЧЕМ ты требуешь именно такой интерфейс. Вот с какой радости?
Отредактировано 05.05.2015 21:09 vdimas . Предыдущая версия .
Re[11]: а попинайте либу
От: vdimas Россия  
Дата: 13.04.15 15:30
Оценка:
Здравствуйте, cyberzlodey, Вы писали:

X>>кстати, если твоя библиотека сессионная — то у каждой сессии может быть свой errno. значит сигнатура должна быть такой: 'int aoc_errno(active_t*)'


C>Да, active_t объектов может быть множество, соответственно обработка ошибок должна привязываться к конкретному объекту. Спасибо за мысль, так и сделаю.


Не слушай бредовых советов. Обработка ошибок должна привязываться к потоку исполнения, а не к объекту. Где для общего случая гарантия, что различные действия над объектом не будут вызваны из различных потоков? Даже если ты сериализуешь доступ к объекту, то после отпускания мьютекса у тебя не может быть никаких предположений о состоянии объекта и о состоянии его "флага ошибки". Поэтому, нужно пользовать только встроенный errno, который привязан к текущему потоку.

Кароч, всё то, что тебе советует "коллега" — это самые вредные советы из виденных мною на этом сайте. Полный П, как грится. ))
Re[12]: а попинайте либу
От: niXman Ниоткуда https://github.com/niXman
Дата: 13.04.15 17:08
Оценка:
вы забыли отметить, что это всего лишь ваше мнение, одно из многих
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.