plibsys
Typedefs | Enumerations | Functions
psemaphore.h File Reference

Semaphore routines. More...

#include <pmacros.h>
#include <ptypes.h>
#include <perror.h>
Include dependency graph for psemaphore.h:

Go to the source code of this file.

Typedefs

typedef P_BEGIN_DECLS enum PSemaphoreAccessMode_ PSemaphoreAccessMode
 Enum with semaphore creation modes. More...
 
typedef struct PSemaphore_ PSemaphore
 Semaphore opaque data structure. More...
 

Enumerations

enum  PSemaphoreAccessMode_ { P_SEM_ACCESS_OPEN = 0, P_SEM_ACCESS_CREATE = 1 }
 Enum with semaphore creation modes. More...
 

Functions

P_LIB_API PSemaphorep_semaphore_new (const pchar *name, pint init_val, PSemaphoreAccessMode mode, PError **error)
 Creates a new PSemaphore object. More...
 
P_LIB_API void p_semaphore_take_ownership (PSemaphore *sem)
 Takes ownership of a semaphore. More...
 
P_LIB_API pboolean p_semaphore_acquire (PSemaphore *sem, PError **error)
 Acquires (P operation) a semaphore. More...
 
P_LIB_API pboolean p_semaphore_release (PSemaphore *sem, PError **error)
 Releases (V operation) a semaphore. More...
 
P_LIB_API void p_semaphore_free (PSemaphore *sem)
 Frees PSemaphore object. More...
 

Detailed Description

Semaphore routines.

Author
Alexander Saprykin

A semaphore is a synchronization primitive which controls access to shared data from the concurrently running threads. Unlike a mutex (which is a particular case of a binary semaphore) it allows concurrent access not to only the one thread.

The semaphore has a counter which means the number of available resources (units). Before entering a critical section a thread must perform the so called P (acquire) operation: if the counter is positive it decrements the counter by 1 and continues execution; otherwise the thread is suspended until the counter becomes positive. Before leaving the critical section the thread must perform the so called V (release) operation: increments the counter by 1 and wakes up a waiting thread from the queue (if any).

You can think about the semaphore as a resource controller: the P operation takes one unit, while the V operation gives one unit back. The thread could not continue execution without taking a resource unit. By setting the initial semaphore counter value you can control how much concurrent threads can work with a shared resource.

This semaphore implementation is process-wide so you can synchronize not only the threads. But it makes this IPC primitive (actually like any other IPC primitive, as well) relatively heavy. Consider using a mutex or a spinlock instead if you do not need to cross a process boundary.

A process-wide semaphore is identified by its name across the system, thus it is also called a named semaphore. Use p_semaphore_new() to open the named semaphore and p_semaphore_free() to close it.

Please note the following platform specific differences:

Use the third argument as P_SEM_ACCESS_CREATE in p_semaphore_new() to reset a semaphore value while opening it. This argument is ignored on Windows. You can also take ownership of the semaphore with p_semaphore_take_ownership() to explicitly remove it from the system after closing.

Typedef Documentation

◆ PSemaphore

typedef struct PSemaphore_ PSemaphore

Semaphore opaque data structure.

◆ PSemaphoreAccessMode

Enum with semaphore creation modes.

Enumeration Type Documentation

◆ PSemaphoreAccessMode_

Enum with semaphore creation modes.

Enumerator
P_SEM_ACCESS_OPEN 

Opens an existing semaphore or creates one with a given value.

P_SEM_ACCESS_CREATE 

Creates semaphore, resets to a given value if exists.

Function Documentation

◆ p_semaphore_acquire()

P_LIB_API pboolean p_semaphore_acquire ( PSemaphore sem,
PError **  error 
)

Acquires (P operation) a semaphore.

Parameters
semPSemaphore to acquire.
[out]errorError report object, NULL to ignore.
Returns
TRUE in case of success, FALSE otherwise.
Since
0.0.1

◆ p_semaphore_free()

P_LIB_API void p_semaphore_free ( PSemaphore sem)

Frees PSemaphore object.

Parameters
semPSemaphore to free.
Since
0.0.1

It doesn't release an acquired semaphore, be careful to not to make a deadlock while removing the acquired semaphore.

◆ p_semaphore_new()

P_LIB_API PSemaphore* p_semaphore_new ( const pchar name,
pint  init_val,
PSemaphoreAccessMode  mode,
PError **  error 
)

Creates a new PSemaphore object.

Parameters
nameSemaphore name.
init_valInitial semaphore value.
modeCreation mode.
[out]errorError report object, NULL to ignore.
Returns
Pointer to a newly created PSemaphore object in case of success, NULL otherwise.
Since
0.0.1

The init_val is used only in one of following cases: a semaphore with the such name doesn't exist, or the semaphore with the such name exists but mode specified as P_SEM_ACCESS_CREATE (non-Windows platforms only). In other cases init_val is ignored. The name is system-wide, so any other process can open that semaphore passing the same name.

◆ p_semaphore_release()

P_LIB_API pboolean p_semaphore_release ( PSemaphore sem,
PError **  error 
)

Releases (V operation) a semaphore.

Parameters
semPSemaphore to release.
[out]errorError report object, NULL to ignore.
Returns
TRUE in case of success, FALSE otherwise.
Since
0.0.1

◆ p_semaphore_take_ownership()

P_LIB_API void p_semaphore_take_ownership ( PSemaphore sem)

Takes ownership of a semaphore.

Parameters
semSemaphore to take ownership.
Since
0.0.1

If you take ownership of a semaphore object, p_semaphore_free() will try to completely unlink it and remove from the system. This is useful on UNIX systems where the semaphore can survive an application crash. On the Windows platform this call has no effect.

The common usage of this call is upon application startup to ensure that the semaphore from the previous crash will be unlinked from the system. To do that, call p_semaphore_new(), take ownership of the semaphore object and remove it with the p_semaphore_free() call. After that, create it again.

You can also do the same thing upon semaphore creation passing P_SEM_ACCESS_CREATE to p_semaphore_new(). The only difference is that you should already know whether this semaphore object is from the previous crash or not.