Просто создайте таблицы сообщений. Это сэкономит время и пространство кодирования.
typedef struct pthread_message {
int code;
const char* text;
} pthread_message;
int pthread_check(int retcode, const char* fname,
pthread_message* messages)
{
if(!retcode) /* Makes the common case fast. */
{
fprintf(stderr, "%s success.\n", fname);
return retcode;
}
/* Look for a message. */
for(; messages->code; ++messages)
if(messages->code == retcode)
{
fprintf(stderr, "%s %s\n", fname, message->text);
return retcode;
}
/* Fall back on standard library. If you lack strerror_r,
then put a generic message here.
*/
char buf[256];
fprintf(stderr, "%s %s\n", fname, strerror_r(retcode, buf, 256));
return retcode;
);
pthread_message pthread_create_messages[] = {
{ EAGAIN, "EAGAIN error: insufficient resources to create another thread,"
" or a system-imposed limit on the number of threads was encountered." },
{ EINVAL, "EINVAL error: invalid settings in attr." },
{ EPERM, "EPERM error: no permission to set the scheduling policy and"
" parameters specified in attr." },
{ 0, 0 } /* End of list. */
};
iret = pthread_check(pthread_create(arg1, arg2, ...), "pthread_create",
pthread_create_messages);
Ничто не мешает вам делиться списками сообщений между функциями, поэтому вы можете писать столько, сколько хотите.
Если вы ненормальный, вы можете сделать из вызова макрос:
#define PTHREAD_CHECK(fname, arglist) \
(pthread_check(fname arglist, #fname, fname##_messages))
iret = PTHREAD_CHECK(pthread_create, (arg1, arg2, ...));
В этом случае разделение списка сообщений означает, что вам нужно создать указатель с соответствующим именем для каждой дополнительной функции, указывающей на список первой функции. Еще намного меньше работы.
Для справки, я просто написал одну функцию проверки с общими сообщениями (за исключением сообщений об успехе, они являются спамом) и использовал ее везде в моей оболочке C ++ вокруг pthread. (Не придирайтесь ко мне по поводу Boost, это было десять лет назад.)