...
Although this example is specific to network I/O, the recv() call could be replaced with any blocking call, and the same behavior would occur.
| Code Block | ||||
|---|---|---|---|---|
| ||||
pthread_mutexattr_t attr;
pthread_mutex_t mutex;
void thread_foo(void *ptr) {
uint32_t num;
int result;
int sock;
/* sock is a connected TCP socket */
if ((result = pthread_mutex_lock(&mutex)) != 0) {
/* Handle Error */
}
if ((result = recv(sock, (void *)&num, sizeof(uint32_t), 0)) < 0) {
/* Handle Error */
}
/* ... */
if ((result = pthread_mutex_unlock(&mutex)) != 0) {
/* Handle Error */
}
}
int main() {
pthread_t thread;
int result;
if ((result = pthread_mutexattr_settype(
&mutex, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
/* Handle Error */
}
if ((result = pthread_mutex_init(&mutex, &attr)) != 0) {
/* Handle Error */
}
if (pthread_create(&thread, NULL,(void *)& thread_foo, NULL) != 0) {
/* Handle Error */
}
/* ... */
pthread_join(thread, NULL);
if ((result = pthread_mutex_destroy(&mutex)) != 0) {
/* Handle Error */
}
return 0;
}
|
...
This compliant solution performs the recv() call when the lock has not been acquired. This causes the blocking behavior to only affect the thread that called the blocking function.
| Code Block | ||||
|---|---|---|---|---|
| ||||
void thread_foo(void *ptr) {
uint32_t num;
int result;
int sock;
/* sock is a connected TCP socket */
if ((result = recv(sock, (void *)&num, sizeof(uint32_t), 0)) < 0) {
/* Handle Error */
}
if ((result = pthread_mutex_lock(&mutex)) != 0) {
/* Handle Error */
}
/* ... */
if ((result = pthread_mutex_unlock(&mutex)) != 0) {
/* Handle Error */
}
}
|
...
This compliant solution performs the recv() call with the parameter o_nonblock, which causes the call to fail if there are no messages available on the socket.
| Code Block | ||||
|---|---|---|---|---|
| ||||
void thread_foo(void *ptr) {
uint32_t num;
int result;
/* sock is a connected TCP socket */
if ((result = recv(sock, (void *)&num, sizeof(uint32_t), O_NONBLOCK)) < 0) {
/* Handle Error */
}
if ((result = pthread_mutex_lock(&mutex)) != 0) {
/* Handle Error */
}
/* ... */
if ((result = pthread_mutex_unlock(&mutex)) != 0) {
/* Handle Error */
}
}
|
...