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 
50 void
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 
70 int
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 
80 struct 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 
109 void
110 io_handle_fini(struct io_handle *handle)
111 {
112  assert(handle);
113  assert(handle->vtab);
114 
115  if (handle->vtab->fini)
116  handle->vtab->fini(handle);
117 }
118 
119 void
120 io_handle_free(struct io_handle *handle)
121 {
122  if (handle) {
123 #if !LELY_NO_THREADS
124  mtx_destroy(&handle->mtx);
125 #endif
126 
127  free(handle);
128  }
129 }
130 
131 void
133 {
134  if (handle) {
135  io_handle_fini(handle);
136  io_handle_free(handle);
137  }
138 }
139 
140 #if !LELY_NO_THREADS
141 
142 void
143 io_handle_lock(struct io_handle *handle)
144 {
145  assert(handle);
146 
147  mtx_lock(&handle->mtx);
148 }
149 
150 void
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
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
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
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