Lely core libraries 2.3.4
handle.c
Go to the documentation of this file.
1
24#include "io.h"
25
26#if !LELY_NO_STDIO
27
28#include <lely/util/errnum.h>
29
30#include <assert.h>
31#include <stdlib.h>
32
33#include "handle.h"
34
37{
38 if (handle != IO_HANDLE_ERROR)
39#if !LELY_NO_ATOMICS
41 &handle->ref, 1, memory_order_relaxed);
42#elif !LELY_NO_THREADS && _WIN32
43 InterlockedIncrementNoFence(&handle->ref);
44#else
45 handle->ref++;
46#endif
47 return handle;
48}
49
50void
52{
53 if (handle == IO_HANDLE_ERROR)
54 return;
55
56#if !LELY_NO_ATOMICS
58 == 1) {
60#elif !LELY_NO_THREADS && _WIN32
61 if (!InterlockedDecrementRelease(&handle->ref)) {
62 MemoryBarrier();
63#else
64 if (handle->ref-- == 1) {
65#endif
66 io_handle_destroy(handle);
67 }
68}
69
70int
72{
73#if !LELY_NO_ATOMICS
74 return handle != IO_HANDLE_ERROR && atomic_load(&handle->ref) == 1;
75#else
76 return handle != IO_HANDLE_ERROR && handle->ref == 1;
77#endif
78}
79
80struct io_handle *
82{
83 assert(vtab);
84 assert(vtab->size >= sizeof(struct io_handle));
85
86 struct io_handle *handle = malloc(vtab->size);
87 if (!handle) {
88 set_errc(errno2c(errno));
89 return NULL;
90 }
91
92 handle->vtab = vtab;
93#if !LELY_NO_ATOMICS
94 atomic_init(&handle->ref, 0);
95#else
96 handle->ref = 0;
97#endif
98 handle->fd = INVALID_HANDLE_VALUE;
99
100#if !LELY_NO_THREADS
101 mtx_init(&handle->mtx, mtx_plain);
102#endif
103
104 handle->flags = 0;
105
106 return handle;
107}
108
109void
111{
112 assert(handle);
113 assert(handle->vtab);
114
115 if (handle->vtab->fini)
116 handle->vtab->fini(handle);
117}
118
119void
121{
122 if (handle) {
123#if !LELY_NO_THREADS
124 mtx_destroy(&handle->mtx);
125#endif
126
127 free(handle);
128 }
129}
130
131void
133{
134 if (handle) {
135 io_handle_fini(handle);
136 io_handle_free(handle);
137 }
138}
139
140#if !LELY_NO_THREADS
141
142void
144{
145 assert(handle);
146
147 mtx_lock(&handle->mtx);
148}
149
150void
152{
153 assert(handle);
154
155 mtx_unlock(&handle->mtx);
156}
157
158#endif // !LELY_NO_THREADS
159
160#endif // !LELY_NO_STDIO
This header file is part of the utilities library; it contains the native and platform-independent er...
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:944
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:46
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
Definition: handle.c:36
void io_handle_fini(struct io_handle *handle)
Finalizes an I/O device handle by invoking its fini method, if available.
Definition: handle.c:110
int io_handle_unique(io_handle_t handle)
Returns 1 if there is only a single reference to the specified I/O device handle, and 0 otherwise.
Definition: handle.c:71
void io_handle_destroy(struct io_handle *handle)
Destroys an I/O device handle.
Definition: handle.c:132
void io_handle_free(struct io_handle *handle)
Frees an I/O device handle.
Definition: handle.c:120
struct io_handle * io_handle_alloc(const struct io_handle_vtab *vtab)
Allocates a new I/O device handle from a virtual table.
Definition: handle.c:81
void io_handle_unlock(struct io_handle *handle)
Unlocks a locked I/O device handle.
Definition: handle.c:151
void io_handle_release(io_handle_t handle)
Decrements the reference count of an I/O device handle.
Definition: handle.c:51
void io_handle_lock(struct io_handle *handle)
Locks an unlocked I/O device handle, so the flags (and other device-specific fields) can safely be ac...
Definition: handle.c:143
This is the internal header file of the I/O handle declarations.
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
Definition: io.h:34
This is the internal header file of the Windows-specific I/O declarations.
@ memory_order_release
A store operation performs a release operation on the affected memory location.
Definition: stdatomic.h:158
@ memory_order_relaxed
No operation orders memory.
Definition: stdatomic.h:131
@ memory_order_acquire
A load operation performs an acquire operation on the affected memory location.
Definition: stdatomic.h:149
#define atomic_fetch_add_explicit(object, operand, order)
Atomically replaces the value at object with *object + operand.
Definition: stdatomic.h:480
void atomic_thread_fence(memory_order order)
Inserts a fence with semantics according to order.
Definition: stdatomic.h:617
#define atomic_load(object)
Equivalent to atomic_load_explicit(object, memory_order_seq_cst).
Definition: stdatomic.h:333
#define atomic_init(obj, value)
Initializes the atomic object at obj with the value value.
Definition: stdatomic.h:222
#define atomic_fetch_sub_explicit(object, operand, order)
Atomically replaces the value at object with *object - operand.
Definition: stdatomic.h:504
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
The virtual table of an I/O device handle.
Definition: handle.h:66
void(* fini)(struct io_handle *handle)
A pointer to the fini method.
Definition: handle.h:75
size_t size
The size (in bytes) of the handle struct.
Definition: handle.h:73
An I/O device handle.
Definition: handle.h:33
int fd
The native file descriptor.
Definition: handle.h:48
atomic_size_t ref
The reference count.
Definition: handle.h:38
int flags
The I/O device flags (any combination of IO_FLAG_NO_CLOSE and IO_FLAG_NONBLOCK).
Definition: handle.h:54
mtx_t mtx
The mutex protecting flags (and other device-specific fields).
Definition: handle.h:57
const struct io_handle_vtab * vtab
A pointer to the virtual table.
Definition: handle.h:35
int mtx_init(mtx_t *mtx, int type)
Creates a mutex object with properties indicated by type, which must have one of the four values:
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
@ mtx_plain
A mutex type that supports neither timeout nor test and return.
Definition: threads.h:109