'Initialization: Function vs. literal
I notice that, in libraries like libpthread, there will be structures which can be allocated in one of two ways. For example, a pthread_mutex_t can be initialized statically via
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
or dynamically via
pthread_mutex_init(&lock);
However, unless I'm missing something, the pthread_mutex_init function is superfluous. That is, couldn't I just do
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
?
Solution 1:[1]
That is, couldn't I just do
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;?
PTHREAD_MUTEX_INITIALIZER expands to an initializer suitable for an object of type pthread_mutex_t, declared at file scope. This must take the form of either a brace-enclosed initializer list or a constant of a type compatible with pthread_mutex_t.
if it is a brace-enclosed initializer list then prefixing it with
(pthread_mutex_t)produces a compound literal of typepthread_mutex_t. Provided that that is not an array type and that it does not directly or indirectly contain anyconstmembers, the C language permits such an assignment.if it is a constant of a type compatible with
pthread_mutex_tthen prefixing it with(pthread_mutex_t)forms a typecast expression, which the C language allows only ifpthread_mutex_tis a void or scalar type. A reasonably likely alternative in this category would be thatpthread_mutex_tis a structure type andPTHREAD_MUTEX_INITIALIZERexpands to a compound literal, and the cast would violate a language constraint in this case.
From a C-language perspective, then, it is not safe to assume that you can perform such an assignment.
From a POSIX perspective, the spec does not specify the form of the expansion of PTHREAD_MUTEX_INITIALIZER, and does not designate it suitable for the use you describe. POSIX-conforming C implementations are therefore free to implement it with any kind of built-in or special-casing they wish, and that is not required to correctly handle any case other than its use as an initializer.
From both those angles, no, it is not safe to do as you describe.
Additionally, as other answers have observed, the initializer macro is suitable only for the case where you are satisfied with the default mutex attributes. If you want non-default attributes, such as for a robust or process-shared mutex, then you must use pthread_mutex_init() to get them. Notwithstanding all the foregoing, then, no, pthread_mutex_init() is not superfluous.
Solution 2:[2]
If I am not mistaken the function is declared like
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
that is it has two parameters.
The function can be called for already existent mutex and the user can specify any acceptable attributes apart from default mutex attributes.
As for the macro PTHREAD_MUTEX_INITIALIZER then according to the description
In cases where default mutex attributes are appropriate, the macro PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are statically allocated. The effect is equivalent to dynamic initialization by a call to pthread_mutex_init() with parameter attr specified as NULL, except that no error checks are performed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | John Bollinger |
| Solution 2 |
