VLC 4.0.0-dev
Loading...
Searching...
No Matches
vlc_cxx_helpers.hpp
Go to the documentation of this file.
1/*****************************************************************************
2 * vlc_cxx_helpers.hpp: C++ helpers
3 *****************************************************************************
4 * Copyright (C) 1998-2018 VLC authors and VideoLAN
5 *
6 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22
23#ifndef VLC_CXX_HELPERS_HPP
24#define VLC_CXX_HELPERS_HPP
25
26/******************************************************************************
27 * C++ memory management helpers
28 ******************************************************************************/
29
30#if defined(__cplusplus) || defined(DOC)
31
32#include <memory>
33#include <utility>
34#include <type_traits>
35#include <string>
36#include <stdexcept>
37
38#ifdef VLC_THREADS_H_
39// Ensure we can use vlc_sem_wait_i11e. We can't declare different versions
40// of the semaphore helper based on vlc_interrupt inclusion, as it would
41// violate ODR
42# include <vlc_interrupt.h>
43#endif
44
45namespace vlc
46{
47
48namespace
49{
50// This helpers need static linkage to avoid their signature to change when
51// building as C++17 (noexcept becomes part of the function signature stating there)
52
53// Wraps a pointer with a custom releaser
54// ex: auto ptr = vlc::wrap_cptr( input_item, &input_item_Release );
55
56///
57/// Wraps a C pointer into a std::unique_ptr
58///
59/// This will convert a C pointer of type T to a std::unique_ptr<T, R> where
60/// T is the pointee type, and R is an arbitrary releaser type.
61///
62/// ptr will be automatically released by calling r( ptr ) when falling out of
63/// scope (whether by returning or by throwing an exception).
64///
65/// @param ptr a C pointer
66/// @param r An instance of a Callable type, that will be invoked with ptr
67/// as its first and only parameter.
68template <typename T, typename Releaser>
69inline auto wrap_cptr( T* ptr, Releaser&& r ) noexcept
70 -> std::unique_ptr<T, typename std::decay<decltype( r )>::type>
71{
72 return std::unique_ptr<T, typename std::decay<decltype( r )>::type>{
73 ptr, std::forward<Releaser>( r )
74 };
75}
76
77///
78/// Wraps a C pointer into a std::unique_ptr
79///
80/// This will convert a C pointer to an array of type T to a
81/// std::unique_ptr<T[], R> where T is the pointee type, and R is an arbitrary
82/// releaser type.
83///
84/// ptr will be automatically released by calling r( ptr ) when falling out of
85/// scope (whether by returning or by throwing an exception).
86///
87/// This function is equivalent to wrap_cptr, except that the returned
88/// unique_ptr provides an operator[] for array access instead of operator* and
89/// operator->
90///
91/// @param ptr a C pointer
92/// @param r An instance of a Callable type, that will be invoked with ptr
93/// as its first and only parameter.
94template <typename T, typename Releaser>
95inline auto wrap_carray( T* ptr, Releaser&& r ) noexcept
96 -> std::unique_ptr<T[], typename std::decay<decltype( r )>::type>
97{
98 return std::unique_ptr<T[], typename std::decay<decltype( r )>::type>{
99 ptr, std::forward<Releaser>( r )
100 };
101}
102
103///
104/// Wraps a C pointer into a std::unique_ptr
105///
106/// This is a convenience wrapper that will use free() as its releaser
107///
108template <typename T>
109inline std::unique_ptr<T, void (*)(void*)> wrap_cptr( T* ptr ) noexcept
110{
111 return wrap_cptr( ptr, &free );
112}
113
114///
115/// Wraps a C pointer into a std::unique_ptr
116///
117/// This is a convenience wrapper that will use free() as its releaser
118///
119template <typename T>
120inline std::unique_ptr<T[], void (*)(void*)> wrap_carray( T* ptr ) noexcept
121{
122 return wrap_carray( ptr, &free );
123}
124
125} // anonymous namespace
126
127///
128/// Wraps a C shared resource having associated Hold() and Release() functions
129//
130/// This is a RAII wrapper for C shared resources (which are manually managed by
131/// calling explicitly their Hold() and Release() functions).
132///
133/// The Hold() and Release() functions must accept exactly one parameter having
134/// type T* (the raw pointer type). Their return type is irrelevant.
135///
136/// To create a new shared resource wrapper type for my_type_t, simply declare:
137///
138/// using MyTypePtr =
139/// ::vlc::vlc_shared_data_ptr<my_type_t, &my_type_Hold, &my_type_Release>;
140///
141/// Then use it to wrap a raw C pointer:
142///
143/// my_type_t *raw_ptr = /* ... */;
144/// MyTypePtr ptr(raw_ptr);
145template <typename T, auto HOLD, auto RELEASE>
147 T *ptr = nullptr;
148
149public:
150 /* default implicit constructor */
152
153 /**
154 * Wrap a shared resource.
155 *
156 * If the pointer is not nullptr, and hold is true, then the resource is
157 * hold (the caller shared ownership is preserved).
158 * If hold is false, then the caller transfers the ownership to this
159 * wrapper.
160 *
161 * \param ptr the raw pointer (can be nullptr)
162 * \param hold whether the resource must be hold
163 */
164 explicit vlc_shared_data_ptr(T *ptr, bool hold = true)
165 : ptr(ptr)
166 {
167 if (ptr && hold)
168 HOLD(ptr);
169 }
170
171 vlc_shared_data_ptr(std::nullptr_t)
172 : ptr(nullptr)
173 {
174 }
175
178
180 : ptr(other.ptr)
181 {
182 other.ptr = nullptr;
183 }
184
186 {
187 if (ptr)
188 RELEASE(ptr);
189 }
190
192 {
193 reset(other.ptr, true);
194 return *this;
195 }
196
198 {
199 reset(other.ptr, false);
200 other.ptr = nullptr;
201 return *this;
202 }
203
204 bool operator==(const vlc_shared_data_ptr &other) const
205 {
206 return ptr == other.ptr;
207 }
208
209 bool operator==(std::nullptr_t) const noexcept
210 {
211 return ptr == nullptr;
212 }
213
214 bool operator!=(const vlc_shared_data_ptr &other) const
215 {
216 return !(*this == other);
217 }
218
219 bool operator!=(std::nullptr_t) const noexcept
220 {
221 return ptr != nullptr;
222 }
223
224 explicit operator bool() const
225 {
226 return ptr;
227 }
228
229 T &operator*() const
230 {
231 return *ptr;
232 }
233
234 T *operator->() const
235 {
236 return ptr;
237 }
238
239 T *get() const
240 {
241 return ptr;
242 }
243
244 /**
245 * Reset the shared resource.
246 *
247 * ptr.reset(rawptr, hold);
248 *
249 * is semantically equivalent to:
250 *
251 * ptr = vlc_shared_data_ptr<...>(rawptr, hold);
252 *
253 * If the pointer is not nullptr, and hold is true, then the resource is
254 * hold (the caller shared ownership is preserved).
255 * If hold is false, then the caller transfers the ownership to this
256 * wrapper.
257 *
258 * \param newptr the raw pointer (can be nullptr)
259 * \param hold whether the resource must be hold
260 */
261 void reset(T *newptr = nullptr, bool hold = true)
262 {
263 if (newptr && hold)
264 HOLD(newptr);
265 if (ptr)
266 RELEASE(ptr);
267 ptr = newptr;
268 }
269};
270
271#if defined(VLC_THREADS_H_) || defined(DOC)
272
273namespace threads
274{
275
276class mutex
277{
278public:
279 mutex() noexcept
280 {
281 vlc_mutex_init( &m_mutex );
282 }
283
284 mutex( const mutex& ) = delete;
285 mutex& operator=( const mutex& ) = delete;
286 mutex( mutex&& ) = delete;
287 mutex& operator=( mutex&& ) = delete;
288
289 void lock() noexcept
290 {
291 vlc_mutex_lock( &m_mutex );
292 }
293 void unlock() noexcept
294 {
295 vlc_mutex_unlock( &m_mutex );
296 }
297
298private:
299 vlc_mutex_t m_mutex;
300 friend class condition_variable;
301 friend class mutex_locker;
302};
303
305{
306public:
308 {
309 vlc_cond_init( &m_cond );
310 }
311 void signal() noexcept
312 {
313 vlc_cond_signal( &m_cond );
314 }
315 void broadcast() noexcept
316 {
317 vlc_cond_broadcast( &m_cond );
318 }
319 void wait( mutex& mutex ) noexcept
320 {
321 vlc_cond_wait( &m_cond, &mutex.m_mutex );
322 }
323 int timedwait( mutex& mutex, vlc_tick_t deadline ) noexcept
324 {
325 return vlc_cond_timedwait( &m_cond, &mutex.m_mutex, deadline );
326 }
327
328private:
329 vlc_cond_t m_cond;
330};
331
333{
334public:
336 : m_mutex( m )
337 {
338 vlc_mutex_lock( m_mutex );
339 }
340 mutex_locker( mutex& m ) noexcept
341 : mutex_locker( &m.m_mutex )
342 {
343 }
345 {
346 vlc_mutex_unlock( m_mutex );
347 }
348 mutex_locker( const mutex_locker& ) = delete;
352
353private:
354 vlc_mutex_t* m_mutex;
355};
356
358{
359public:
360 semaphore() noexcept
361 {
362 vlc_sem_init( &m_sem, 0 );
363 }
364 semaphore( unsigned int count ) noexcept
365 {
366 vlc_sem_init( &m_sem, count );
367 }
369 {
370 }
371
372 semaphore( const semaphore& ) = delete;
373 semaphore& operator=( const semaphore& ) = delete;
374 semaphore( semaphore&& ) = delete;
376
377 int post() noexcept
378 {
379 return vlc_sem_post( &m_sem );
380 }
381 void wait() noexcept
382 {
383 vlc_sem_wait( &m_sem );
384 }
385
386 int wait_i11e() noexcept
387 {
388 return vlc_sem_wait_i11e( &m_sem );
389 }
390
391private:
392 vlc_sem_t m_sem;
393};
394
395}
396
397#endif // VLC_THREADS_H_
398
399#ifdef VLC_URL_H
400
401class url : public vlc_url_t
402{
403public:
404 class invalid : public std::runtime_error
405 {
406 public:
407 explicit invalid( const char* url )
408 : std::runtime_error( std::string{ "Invalid url: " } + url )
409 {
410 }
411 };
412
413 url()
414 {
415 psz_buffer = nullptr;
416 psz_pathbuffer = nullptr;
417 psz_host = nullptr;
418 }
419
420 explicit url( const char* str )
421 {
422 if ( vlc_UrlParse( this, str ) )
423 {
424 vlc_UrlClean( this );
425 throw invalid( str );
426 }
427 }
428
429 explicit url( const std::string& str )
430 : url( str.c_str() )
431 {
432 }
433
434 ~url()
435 {
436 vlc_UrlClean(this);
437 }
438
439 url( const url& ) = delete;
440 url& operator=( const url& ) = delete;
441
442 url( url&& u ) noexcept
443 : vlc_url_t( u )
444 {
445 u.psz_buffer = nullptr;
446 u.psz_pathbuffer = nullptr;
447 u.psz_host = nullptr;
448 }
449
450 url& operator=( url&& u ) noexcept
451 {
452 vlc_UrlClean( this );
453 *(static_cast<vlc_url_t*>( this )) = u;
454 u.psz_buffer = nullptr;
455 u.psz_pathbuffer = nullptr;
456 u.psz_host = nullptr;
457 return *this;
458 }
459};
460
461#endif
462
463} // namespace vlc
464
465#endif
466
467#endif // VLC_CXX_HELPERS_HPP
Definition vlc_cxx_helpers.hpp:305
void wait(mutex &mutex) noexcept
Definition vlc_cxx_helpers.hpp:319
int timedwait(mutex &mutex, vlc_tick_t deadline) noexcept
Definition vlc_cxx_helpers.hpp:323
void signal() noexcept
Definition vlc_cxx_helpers.hpp:311
condition_variable() noexcept
Definition vlc_cxx_helpers.hpp:307
void broadcast() noexcept
Definition vlc_cxx_helpers.hpp:315
Definition vlc_cxx_helpers.hpp:333
mutex_locker & operator=(const mutex_locker &)=delete
mutex_locker(mutex_locker &&)=delete
~mutex_locker()
Definition vlc_cxx_helpers.hpp:344
mutex_locker(mutex &m) noexcept
Definition vlc_cxx_helpers.hpp:340
mutex_locker(const mutex_locker &)=delete
mutex_locker(vlc_mutex_t *m) noexcept
Definition vlc_cxx_helpers.hpp:335
mutex_locker & operator=(mutex_locker &&)=delete
Definition vlc_cxx_helpers.hpp:277
mutex(const mutex &)=delete
mutex(mutex &&)=delete
mutex & operator=(mutex &&)=delete
void unlock() noexcept
Definition vlc_cxx_helpers.hpp:293
mutex() noexcept
Definition vlc_cxx_helpers.hpp:279
mutex & operator=(const mutex &)=delete
void lock() noexcept
Definition vlc_cxx_helpers.hpp:289
Definition vlc_cxx_helpers.hpp:358
semaphore(unsigned int count) noexcept
Definition vlc_cxx_helpers.hpp:364
~semaphore()
Definition vlc_cxx_helpers.hpp:368
semaphore & operator=(const semaphore &)=delete
void wait() noexcept
Definition vlc_cxx_helpers.hpp:381
semaphore(const semaphore &)=delete
semaphore & operator=(semaphore &&)=delete
semaphore() noexcept
Definition vlc_cxx_helpers.hpp:360
semaphore(semaphore &&)=delete
int post() noexcept
Definition vlc_cxx_helpers.hpp:377
int wait_i11e() noexcept
Definition vlc_cxx_helpers.hpp:386
Wraps a C shared resource having associated Hold() and Release() functions.
Definition vlc_cxx_helpers.hpp:146
vlc_shared_data_ptr(const vlc_shared_data_ptr &other)
Definition vlc_cxx_helpers.hpp:176
vlc_shared_data_ptr & operator=(vlc_shared_data_ptr &&other) noexcept
Definition vlc_cxx_helpers.hpp:197
bool operator==(const vlc_shared_data_ptr &other) const
Definition vlc_cxx_helpers.hpp:204
vlc_shared_data_ptr(std::nullptr_t)
Definition vlc_cxx_helpers.hpp:171
vlc_shared_data_ptr(T *ptr, bool hold=true)
Wrap a shared resource.
Definition vlc_cxx_helpers.hpp:164
T * operator->() const
Definition vlc_cxx_helpers.hpp:234
bool operator!=(std::nullptr_t) const noexcept
Definition vlc_cxx_helpers.hpp:219
bool operator==(std::nullptr_t) const noexcept
Definition vlc_cxx_helpers.hpp:209
T * get() const
Definition vlc_cxx_helpers.hpp:239
void reset(T *newptr=nullptr, bool hold=true)
Reset the shared resource.
Definition vlc_cxx_helpers.hpp:261
bool operator!=(const vlc_shared_data_ptr &other) const
Definition vlc_cxx_helpers.hpp:214
~vlc_shared_data_ptr()
Definition vlc_cxx_helpers.hpp:185
vlc_shared_data_ptr & operator=(const vlc_shared_data_ptr &other)
Definition vlc_cxx_helpers.hpp:191
T & operator*() const
Definition vlc_cxx_helpers.hpp:229
vlc_shared_data_ptr(vlc_shared_data_ptr &&other) noexcept
Definition vlc_cxx_helpers.hpp:179
size_t count
Definition core.c:403
void vlc_cond_signal(vlc_cond_t *cond)
Wakes up one thread waiting on a condition variable.
Definition threads.c:193
int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex, vlc_tick_t deadline)
Waits on a condition variable up to a certain date.
Definition threads.c:292
void vlc_cond_broadcast(vlc_cond_t *cond)
Wakes up all threads waiting on a condition variable.
Definition threads.c:220
void vlc_cond_wait(vlc_cond_t *cond, vlc_mutex_t *mutex)
Waits on a condition variable.
Definition threads.c:280
void vlc_cond_init(vlc_cond_t *cond)
Initializes a condition variable.
Definition threads.c:174
int vlc_sem_wait_i11e(vlc_sem_t *sem)
Interruptible variant of vlc_sem_wait().
Definition interrupt.c:206
void vlc_mutex_unlock(vlc_mutex_t *mtx)
Releases a mutex.
Definition threads.c:149
void vlc_mutex_init(vlc_mutex_t *mtx)
Initializes a fast mutex.
Definition threads.c:75
void vlc_mutex_lock(vlc_mutex_t *mtx)
Acquires a mutex.
Definition threads.c:95
void vlc_sem_wait(vlc_sem_t *sem)
Waits on a semaphore.
Definition threads.c:331
void vlc_sem_init(vlc_sem_t *sem, unsigned value)
Initializes a semaphore.
Definition threads.c:310
int vlc_sem_post(vlc_sem_t *sem)
Increments the value of a semaphore.
Definition threads.c:315
int vlc_UrlParse(vlc_url_t *url, const char *str)
Parses an URI or IRI.
Definition url.c:581
Definition vlc_cxx_helpers.hpp:46
Condition variable.
Definition vlc_threads.h:270
Mutex.
Definition vlc_threads.h:143
Semaphore.
Definition vlc_threads.h:368
Definition vlc_url.h:146
char * psz_buffer
Definition vlc_url.h:156
void vlc_UrlClean(vlc_url_t *restrict url)
Definition url.c:621
This file declares interruptible sleep functions.
int64_t vlc_tick_t
High precision date or time interval.
Definition vlc_tick.h:48