Genivia - Thread and mutex functions

|  | Home | Documentation | Thread and mutex functions updated Mon Apr 22 2024 by Robert van Engelen |

- Main Page
- Modules
- Classes
- Files

Macros
Thread and mutex functions

This module defines portable thread and mutex functions. More...

## Macros
#define | THREAD_TYPE
| Type of a thread (thread ID) More...
#define | THREAD_ID
| The thread ID of self. More...
#define | THREAD_CREATE(tidptr, funcptr, argptr)
| Create a new thread. More...
#define | THREAD_CREATEX(tidptr, funcptr, argptr)
| Create a new joinable thread (Windows only) More...
#define | THREAD_CLOSE(tid)
| Close the thread ID handle created by `THREAD_CREATEX` (Windows only) More...
#define | THREAD_DETACH(tid)
| Detach a thread. More...
#define | THREAD_JOIN(tid)
| Join a thread. More...
#define | THREAD_EXIT
| Exit the current thread. More...
#define | THREAD_CANCEL(tid)
| Cancel a thread. More...
#define | MUTEX_TYPE
| Type of a mutex object. More...
#define | MUTEX_INITIALIZER
| Mutex initializer object. More...
#define | MUTEX_SETUP(mx)
| Mutex object initialization. More...
#define | MUTEX_CLEANUP(mx)
| Mutex object finalization. More...
#define | MUTEX_LOCK(mx)
| Mutex object lock. More...
#define | MUTEX_UNLOCK(mx)
| Mutex object unlock. More...
#define | COND_TYPE
| The type of a condition variable. More...
#define | COND_SETUP(cv)
| Condition variable initialization. More...
#define | COND_CLEANUP(cv)
| Condition variable finalization. More...
#define | COND_SIGNAL(cv)
| Condition variable signal operation. More...
#define | COND_WAIT(mx, cv)
| Condition variable wait operation. More...

## Detailed Description

This module defines portable thread and mutex functions.

- `THREAD_TYPE`
- `THREAD_ID`
- `THREAD_CREATE(tidptr, funcptr, argptr)`
- `THREAD_CREATEX(tidptr, funcptr, argptr)` (for Windows)
- `THREAD_CLOSE(tid)` (for Windows)
- `THREAD_DETACH(tid)`
- `THREAD_JOIN(tid)`
- `THREAD_EXIT`
- `THREAD_CANCEL(tid)`
- `MUTEX_TYPE`
- `MUTEX_INITIALIZER`
- `MUTEX_SETUP(mx)`
- `MUTEX_CLEANUP(mx)`
- `MUTEX_LOCK(mx)`
- `MUTEX_UNLOCK(mx)`
- `COND_TYPE`
- `COND_SETUP(cv)`
- `COND_CLEANUP(cv)`
- `COND_SIGNAL(cv)`
- `COND_WAIT(mx, cv)`

## Macro Definition Documentation

#define COND_CLEANUP | ( |  | cv | ) |

Condition variable finalization.

This macro finalizes the specified condition variable.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Parameters

  cv | `COND_TYPE` condition variable

#define COND_SETUP | ( |  | cv | ) |

Condition variable initialization.

This macro initializes the specified condition variable.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Parameters

  cv | `COND_TYPE` condition variable

#define COND_SIGNAL | ( |  | cv | ) |

Condition variable signal operation.

This macro signals the specified condition variable.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Parameters

  cv | `COND_TYPE` condition variable

#define COND_TYPE

The type of a condition variable.

This macro represents a portable condition variable

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

#define COND_WAIT | ( |  | mx,
|  |  | cv
| ) |  |

Condition variable wait operation.

This macro waits on the specified condition variable and releases the mutex while waiting.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Parameters

  mx | `MUTEX_TYPE` mutex object
  cv | `COND_TYPE` condition variable

#define MUTEX_CLEANUP | ( |  | mx | ) |

Mutex object finalization.

This macro finalizes a mutex object.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
MUTEX_TYPE lock;
MUTEX_SETUP(lock);
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
... // some other work to do
MUTEX_CLEANUP(lock);

Parameters

  mx | `MUTEX_TYPE` mutex object

#define MUTEX_INITIALIZER

Mutex initializer object.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
static MUTEX_TYPE lock = MUTEX_INITIALIZER;
int main()
{
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
...
}

#define MUTEX_LOCK | ( |  | mx | ) |

Mutex object lock.

This macro acquires mutex.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
MUTEX_TYPE lock;
MUTEX_SETUP(lock);
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
... // some other work to do
MUTEX_CLEANUP(lock);

Parameters

  mx | `MUTEX_TYPE` mutex object

#define MUTEX_SETUP | ( |  | mx | ) |

Mutex object initialization.

This macro initializes a mutex object.

To declare and initialize static mutex objects, see `MUTEX_INITIALIZER`.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
MUTEX_TYPE lock;
MUTEX_SETUP(lock);
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
... // some other work to do
MUTEX_CLEANUP(lock);

Parameters

  mx | `MUTEX_TYPE` mutex object

#define MUTEX_TYPE

Type of a mutex object.

This macro represents a portable mutex object type.

To declare and initialize static mutex objects, see `MUTEX_INITIALIZER`.

Example:

#include "plugin/threads.h"
MUTEX_TYPE lock;
MUTEX_SETUP(lock);
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
... // some other work to do
MUTEX_CLEANUP(lock);

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

#define MUTEX_UNLOCK | ( |  | mx | ) |

Mutex object unlock.

This macro releases mutex.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
MUTEX_TYPE lock;
MUTEX_SETUP(lock);
... // some other work to do
MUTEX_LOCK(lock);
... // critical section
MUTEX_UNLOCK(lock);
... // some other work to do
MUTEX_CLEANUP(lock);

Parameters

  mx | `MUTEX_TYPE` mutex object

#define THREAD_CANCEL | ( |  | tid | ) |

Cancel a thread.

This macro requests that the specified thread be cancelled.

POSIX threads can be cancelled when currently in a cancellation point, which are certain functions that will terminate the thread when the thread is cancelled.

Warning
  Cancelling a thread may lead to resource leaks when the thread has no mechanism to clean up its state (memory allocated, files and sockets opened etc.), unless cleanup handlers are defined for each thread, e.g. with `pthread_cleanup_push`. Even when defining a cleanup function, care must be taken to prevent resource leaks that may be caused by cancellation points that sit between a resouce acquisition operation and its release operation, e.g. between a file open and close operation some read/write functions may be called that are cancellation points. The gSOAP engine and plugins are designed to maintain the engine state using resource pointers to resources (memory, files, sockets etc.) in the `soap` context. The context should be passed to the cleanup function when added with `pthread_cleanup_push` to cleanup the context. This cleanup function should call `soap_destroy`, `soap_end`, and `soap_free` (in that order). However, use `THREAD_CANCEL` at your own risk. User-defined service operations and other non-gSOAP code may not meet the requirements to perform a safe `THREAD_CANCEL` unless the cleanup functions are carefully designed. Alternatively, a simpler approach with a global flag (a flag per thread) may suffice: set the flag by the main thread to indicate termination is requested of the specific thread and check this flag in the user-defined service operations to terminate the service operation with an error, e.g. `return 500`.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "soapH.h"
#include "plugin/threads.h"
struct soap *soap = soap_new();
soap->bind_flags = SO_REUSEADDR; // immediate port reuse
soap->accept_timeout = 3600; // exit loop when no request arrives in one hour
soap->send_timeout = soap_recv_timeout = 5; // 5 seconds max socket stall time (unlimited by default)
soap->transfer_timeout = 30; // 30 seconds max message transfer time (unlimited by default)
soap->recv_maxlength = 1048576; // limit messages received to 1MB (2GB by default)
if (soap_valid_socket(soap_bind(soap, NULL, PORTNUM, BACKLOG)))
{
while (1)
{
if (soap_valid_socket(soap_accept(soap)))
{
THREAD_TYPE tid;
struct soap *tsoap = soap_copy(soap);
if (!tsoap)
soap_force_closesock(soap);
else
while (THREAD_CREATE(&tid, (void*(*)(void*))&accept_request, (void*)tsoap))
sleep(1); // failed, try again
}
else if (soap->errnum) // accept failed, try again after 1 second
{
soap_print_fault(soap, stderr);
sleep(1);
}
else // accept_timeout timed out, quit looping
{
break;
}
soap_destroy(soap);
soap_end(soap);
}
}
soap_free(soap);
void *accept_request(struct soap *soap)
{
THREAD_TYPE tid;
struct soap *tsoap;
THREAD_DETACH(THREAD_ID);
// create a new thread that is timed to execute for max 10 seconds
tsoap = soap_copy(soap);
if (!tsoap)
{
soap_force_closesock(soap);
}
else
{
while (THREAD_CREATE(&tid, (void*(*)(void*))&process_request, (void*)tsoap))
sleep(1); // failed, try again
// allow serving the request by the new thread for up to 30 seconds max
sleep(30);
// terminate process_request thread
THREAD_CANCEL(tid);
}
// clean up
soap_destroy(soap);
soap_end(soap);
soap_free(soap);
return NULL;
}
void *process_request(struct soap *soap)
{
// add the cleanup function
pthread_cleanup_push((void(*)(void*))&cleanup, (void*)soap);
soap_serve(soap);
// remove the cleanup function and call it to cleanup the context
pthread_cleanup_pop(1);
return NULL;
}
void cleanup(struct soap *soap)
{
soap_destroy(soap);
soap_end(soap);
soap_free(soap);
}

Parameters

  tid | `THREAD_TYPE` thread ID to cancel

#define THREAD_CLOSE | ( |  | tid | ) |

Close the thread ID handle created by `THREAD_CREATEX` (Windows only)

#define THREAD_CREATE | ( |  | tidptr,
|  |  | funcptr,
|  |  | argptr
| ) |  |

Create a new thread.

This macro creates a new thread and runs the specified function with the argument parameter passed to this function.

Warning
  On Windows platforms `THREAD_CREATE` uses `_beginthread` which returns a thread ID handle that cannot be joined. To join a thread use `THREAD_CREATEX(&tid, func, arg)` then `THREAD_JOIN`. Don't forget to `THREAD_CLOSE(tid)` afterwards:
  #include "plugin/threads.h"
  THREAD_TYPE tid;
  while (THREAD_CREATEX(&tid, (void*(*)(void*))&process_request, (void*)tsoap)))
  sleep(1); // failed, try again
  ... // some other work to do
  THREAD_JOIN(tid); // wait for the thread to terminate and join
  THREAD_CLOSE(tid); // close handle
  ... // some other work to do

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
THREAD_TYPE tid;
while (THREAD_CREATE(&tid, (void*(*)(void*))&process_request, (void*)tsoap)))
sleep(1); // failed, try again
... // some other work to do
THREAD_JOIN(tid); // optional: to wait for the thread to terminate and join (see warning)
... // some other work to do

Parameters

  tidptr | pointer to `THREAD_TYPE` thread ID to assign
  funcptr | function to run by the new thread
  argptr | the argument (a pointer) to pass to the function when called

Returns
  zero on success and nonzero on failure

#define THREAD_CREATEX | ( |  | tidptr,
|  |  | funcptr,
|  |  | argptr
| ) |  |

Create a new joinable thread (Windows only)

On Windows platforms `THREAD_CREATE` uses `_beginthread` which returns a thread ID handle that cannot be joined. To join a thread use `THREAD_CREATEX(&tid, func, arg)` then `THREAD_JOIN`. Don't forget to `THREAD_CLOSE(tid)` afterwards.

#define THREAD_DETACH | ( |  | tid | ) |

Detach a thread.

This macro detaches the specified thread. A detached thread cannot be joined back with the thread that created it. When a detached thread terminates, its resources are automatically released back to the system without the need for another thread to join with the terminated thread.

This macro has no effect on Windows platforms, see `THREAD_CREATE`.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

#include "plugin/threads.h"
THREAD_DETACH(THREAD_ID); // detach self

Parameters

  tid | `THREAD_TYPE` thread ID to detach

#define THREAD_EXIT

Exit the current thread.

This macro terminates the current thread.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

#define THREAD_ID

The thread ID of self.

This macro represents the current thread ID, i.e. self.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

#define THREAD_JOIN | ( |  | tid | ) |

Join a thread.

This macro waits for the termination of the specified thread to join it.

This macro requires `THREAD_CREATEX` and `THREAD_CLOSE` on Windows plaforms.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Parameters

  tid | `THREAD_TYPE` thread ID to join

#define THREAD_TYPE

Type of a thread (thread ID)

This macro represents a portable thread ID type.

Note
  This macro is declared in `gsoap/plugin/threads.h` and requires compilation of `gsoap/plugin/threads.c` on Windows platforms.

Example:

THREAD_TYPE tid;
while (THREAD_CREATE(&tid, (void*(*)(void*))&process_request, (void*)tsoap)))
sleep(1); // failed, try again