LINUX.ORG.RU

СИ макросы понеслось


0

0

#define CLEANUPBLK(name) \
int __##name##_cleanup_code; \
{

#define CLEANUPBEG(name, val) \
} \
__##name##_cleanup_clean: \
__##name##_cleanup_code = val; \
__##name##_cleanup_select_clean: \
switch (__##name##_cleanup_code) \
{ \
  case val:

#define CLEANUPNEXT(name, val) \
  case val:

#define CLEANUPEND(name) \
  default: \
    goto __##name##_cleanup_break; \
    goto __##name##_cleanup_clean; \
    goto __##name##_cleanup_select_clean; \
} \
__##name##_cleanup_break:

#define CLEANUPALL(name) \
goto __##name##_cleanup_clean

#define CLEANUPBRK(name) \
goto __##name##_cleanup_break

#define CLEANUPSEL(name, val) \
__##name##_cleanup_code = val; \
goto __##name##_cleanup_select_clean

int main()
{
  CLEANUPBLK()
  {
     if (!init1())
       CLEANUPBRK();

     if (!init2())
       CLEANUPSEL(, 1);

     if (!init3())
       CLEANUPSEL(, 2);

     if (!init4())
       CLEANUPSEL(, 3);
     
     if (!some_func())
       CLEANUPALL();

     some_func2();
  }
  CLEANUPBEG(, 0)
  {
     clean4();
  }
  CLEANUPNEXT(, 3)
  {
     clean3();
  }
  CLEANUPNEXT(, 2)
  {
     clean2();
  }
  CLEANUPNEXT(, 1)
  {
     clean1();
  }
  CLEANUPEND();

  return 0;
}

Интересно узнать кто как решает данную проблему в языке си? init - берет ресурс, clean - освобождает ресурс.
PS: Раньше на си серьезно не писал, а писал на с++ и что то слишком много макросов начал использовать.

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

> А реализовать нормальные "локальные исключения" тебе не позволит ограниченность препроцессора Си.

Мне кажется коряво все же можно. Идея конечно -- делать это через goto.

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

а еще можно, если у тебя init/free однотипно называются:

#define WITH(res, arg, block) { res* resource=init_##res(arg); if(!res) goto end; block free_##res(res*); end: }

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

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

#define WITH(res, arg, block) { res* res##var=init_##res(arg); if(!res##var) goto end; block free_##res(res##var); end: }

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

typedef struct TAG_resources_list
  {
  struct TAG_resources_list *prev;

  void  *resource;
  void (*release)(void *);
  } T_resources_list;

alex4
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.