1 /*****************************************************************************
2 * vlc_cxx_helpers.hpp: C++ helpers
3 *****************************************************************************
4 * Copyright (C) 1998-2018 VLC authors and VideoLAN
6 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
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.
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.
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 *****************************************************************************/
23 #ifndef VLC_CXX_HELPERS_HPP
24 #define VLC_CXX_HELPERS_HPP
26 /******************************************************************************
27 * C++ memory management helpers
28 ******************************************************************************/
34 #include <type_traits>
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
42 # include <vlc_interrupt.h>
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)
53 // Wraps a pointer with a custom releaser
54 // ex: auto ptr = vlc_wrap_cptr( input_item, &input_item_Release );
57 /// Wraps a C pointer into a std::unique_ptr
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.
62 /// ptr will be automatically released by calling r( ptr ) when falling out of
63 /// scope (whether by returning of by throwing an exception
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.
68 template <typename T
, typename Releaser
>
69 inline auto wrap_cptr( T
* ptr
, Releaser
&& r
) noexcept
70 -> std::unique_ptr
<T
, typename
std::decay
<decltype( r
)>::type
>
72 return std::unique_ptr
<T
, typename
std::decay
<decltype( r
)>::type
>{
73 ptr
, std::forward
<Releaser
>( r
)
78 /// Wraps a C pointer into a std::unique_ptr
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
84 /// ptr will be automatically released by calling r( ptr ) when falling out of
85 /// scope (whether by returning of by throwing an exception
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
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.
94 template <typename T
, typename Releaser
>
95 inline auto wrap_carray( T
* ptr
, Releaser
&& r
) noexcept
96 -> std::unique_ptr
<T
[], typename
std::decay
<decltype( r
)>::type
>
98 return std::unique_ptr
<T
[], typename
std::decay
<decltype( r
)>::type
>{
99 ptr
, std::forward
<Releaser
>( r
)
104 /// Wraps a C pointer into a std::unique_ptr
106 /// This is a convenience wrapper that will use free() as its releaser
108 template <typename T
>
109 inline std::unique_ptr
<T
, void (*)(void*)> wrap_cptr( T
* ptr
) noexcept
111 return wrap_cptr( ptr
, &free
);
115 /// Wraps a C pointer into a std::unique_ptr
117 /// This is a convenience wrapper that will use free() as its releaser
119 template <typename T
>
120 inline std::unique_ptr
<T
[], void (*)(void*)> wrap_carray( T
* ptr
) noexcept
122 return wrap_carray( ptr
, &free
);
125 } // anonymous namespace
128 /// Wraps a C shared resource having associated Hold() and Release() functions
130 /// This is a RAII wrapper for C shared resources (which are manually managed by
131 /// calling explicitly their Hold() and Release() functions).
133 /// The Hold() and Release() functions must accept exactly one parameter having
134 /// type T* (the raw pointer type). Their return type is irrelevant.
136 /// To create a new shared resource wrapper type for my_type_t, simply declare:
138 /// using MyTypePtr =
139 /// vlc_shared_data_ptr_type(my_type_t, my_type_Hold, my_type_Release);
141 /// Then use it to wrap a raw C pointer:
143 /// my_type_t *raw_ptr = /* ... */;
144 /// MyTypePtr ptr(raw_ptr);
146 // In C++17, the template declaration could be replaced by:
147 // template<typename T, auto HOLD, auto RELEASE>
148 template <typename T
, typename H
, typename R
, H HOLD
, R RELEASE
>
149 class vlc_shared_data_ptr
{
153 /* default implicit constructor */
154 vlc_shared_data_ptr() = default;
157 * Wrap a shared resource.
159 * If the pointer is not nullptr, and hold is true, then the resource is
160 * hold (the caller shared ownership is preserved).
161 * If hold is false, then the caller transfers the ownership to this
164 * \param ptr the raw pointer (can be nullptr)
165 * \param hold whether the resource must be hold
167 explicit vlc_shared_data_ptr(T
*ptr
, bool hold
= true)
174 vlc_shared_data_ptr(const vlc_shared_data_ptr
&other
)
175 : vlc_shared_data_ptr(other
.ptr
) {}
177 vlc_shared_data_ptr(vlc_shared_data_ptr
&&other
) noexcept
183 ~vlc_shared_data_ptr()
189 vlc_shared_data_ptr
&operator=(const vlc_shared_data_ptr
&other
)
191 reset(other
.ptr
, true);
195 vlc_shared_data_ptr
&operator=(vlc_shared_data_ptr
&&other
) noexcept
197 reset(other
.ptr
, false);
202 bool operator==(const vlc_shared_data_ptr
&other
) const
204 return ptr
== other
.ptr
;
207 bool operator==(std::nullptr_t
) const noexcept
209 return ptr
== nullptr;
212 bool operator!=(const vlc_shared_data_ptr
&other
) const
214 return !(*this == other
);
217 bool operator!=(std::nullptr_t
) const noexcept
219 return ptr
!= nullptr;
222 explicit operator bool() const
232 T
*operator->() const
243 * Reset the shared resource.
245 * ptr.reset(rawptr, hold);
247 * is semantically equivalent to:
249 * ptr = vlc_shared_data_ptr<...>(rawptr, hold);
251 * If the pointer is not nullptr, and hold is true, then the resource is
252 * hold (the caller shared ownership is preserved).
253 * If hold is false, then the caller transfers the ownership to this
256 * \param ptr the raw pointer (can be nullptr)
257 * \param hold whether the resource must be hold
259 void reset(T
*newptr
= nullptr, bool hold
= true)
269 // useful due to the unnecessarily complex template declaration before C++17
270 #define vlc_shared_data_ptr_type(type, hold, release) \
271 ::vlc::vlc_shared_data_ptr<type, decltype(&hold), decltype(&release), \
274 #ifdef VLC_THREADS_H_
284 vlc_mutex_init( &m_mutex
);
287 mutex( const mutex
& ) = delete;
288 mutex
& operator=( const mutex
& ) = delete;
289 mutex( mutex
&& ) = delete;
290 mutex
& operator=( mutex
&& ) = delete;
294 vlc_mutex_lock( &m_mutex
);
296 void unlock() noexcept
298 vlc_mutex_unlock( &m_mutex
);
303 friend class condition_variable
;
304 friend class mutex_locker
;
307 class condition_variable
310 condition_variable() noexcept
312 vlc_cond_init( &m_cond
);
314 void signal() noexcept
316 vlc_cond_signal( &m_cond
);
318 void broadcast() noexcept
320 vlc_cond_broadcast( &m_cond
);
322 void wait( mutex
& mutex
) noexcept
324 vlc_cond_wait( &m_cond
, &mutex
.m_mutex
);
326 int timedwait( mutex
& mutex
, vlc_tick_t deadline
) noexcept
328 return vlc_cond_timedwait( &m_cond
, &mutex
.m_mutex
, deadline
);
338 mutex_locker( vlc_mutex_t
* m
) noexcept
341 vlc_mutex_lock( m_mutex
);
343 mutex_locker( mutex
& m
) noexcept
344 : mutex_locker( &m
.m_mutex
)
349 vlc_mutex_unlock( m_mutex
);
351 mutex_locker( const mutex_locker
& ) = delete;
352 mutex_locker
& operator=( const mutex_locker
& ) = delete;
353 mutex_locker( mutex_locker
&& ) = delete;
354 mutex_locker
& operator=( mutex_locker
&& ) = delete;
357 vlc_mutex_t
* m_mutex
;
365 vlc_sem_init( &m_sem
, 0 );
367 semaphore( unsigned int count
) noexcept
369 vlc_sem_init( &m_sem
, count
);
375 semaphore( const semaphore
& ) = delete;
376 semaphore
& operator=( const semaphore
& ) = delete;
377 semaphore( semaphore
&& ) = delete;
378 semaphore
& operator=( semaphore
&& ) = delete;
382 return vlc_sem_post( &m_sem
);
386 vlc_sem_wait( &m_sem
);
389 int wait_i11e() noexcept
391 return vlc_sem_wait_i11e( &m_sem
);
400 #endif // VLC_THREADS_H_
404 class url
: public vlc_url_t
407 class invalid
: public std::runtime_error
410 invalid( const char* url
)
411 : std::runtime_error( std::string
{ "Invalid url: " } + url
)
418 psz_buffer
= nullptr;
419 psz_pathbuffer
= nullptr;
423 url( const char* str
)
425 if ( vlc_UrlParse( this, str
) )
426 throw invalid( str
);
429 url( const std::string
& str
)
439 url( const url
& ) = delete;
440 url
& operator=( const url
& ) = delete;
442 url( url
&& u
) noexcept
445 u
.psz_buffer
= nullptr;
446 u
.psz_pathbuffer
= nullptr;
447 u
.psz_host
= nullptr;
450 url
& operator=( url
&& u
) noexcept
452 *(static_cast<vlc_url_t
*>( this )) = u
;
453 u
.psz_buffer
= nullptr;
454 u
.psz_pathbuffer
= nullptr;
455 u
.psz_host
= nullptr;
466 #endif // VLC_CXX_HELPERS_HPP