Добрый день.
Возник такой философский вопрос - куда лучше всего помещать блокировку контекста модуля:
- В сам контекст и делать функции lock/unlock внутри модуля при вызове каждой функции. Примерно так
struct mytype { mutex_t m; /* some data to protect */ } void mytype_do_something(mytype *ctx) { mutex_lock(ctx->m); /* do something with data */ mutex_unlock(ctx->m); }
- В сам контекст, но сделать API функции lock/unlock, которые должен вызывать пользователь модуля
struct mytype { mutex_t m; /* some data to protect */ } void mytype_lock(mytype *ctx) { mutex_lock(ctx->m); } void mytype_unlock(mytype *ctx) { mutex_unlock(ctx->m); } void mytype_do_something(mytype *ctx) { /* do something with data with the assumption that user called mytype_lock() */ }
- Возложить ответственность за синхронизацию на пользователя модуля, т.е. мьютекс, как минимум будет определен на уровень выше
void thread_func(void *user_ctx) { mytype *ctx = ((thread_ctx *)user_ctx)->ctx; mutex_t m = ((thread_ctx *)user_ctx)->m; /* ... */ mutex_lock(m); mytype_do_something(ctx); mutex_unlock(m); } int main() { mytype *ctx; mutex_t m; /* init ctx and mutex */ /* start threads */ /* ... */ }
Лично у самого предпочтения идут с конца списка в начало, т.е. сначала 3, потом 2 и меньше всего нравится скрытая блокировка.