access: linsys: clear some warnings
[vlc.git] / include / vlc_cxx_helpers.hpp
blob5050d1ddb0c768448a53cc07ab6c0577d1a70315
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 ******************************************************************************/
30 #ifdef __cplusplus
32 #include <memory>
33 #include <utility>
34 #include <type_traits>
36 #ifdef VLC_THREADS_H_
37 // Ensure we can use vlc_sem_wait_i11e. We can't declare different versions
38 // of the semaphore helper based on vlc_interrupt inclusion, as it would
39 // violate ODR
40 # include <vlc_interrupt.h>
41 #endif
43 namespace vlc
46 namespace
48 // This helpers need static linkage to avoid their signature to change when
49 // building as C++17 (noexcept becomes part of the function signature stating there)
51 // Wraps a pointer with a custom releaser
52 // ex: auto ptr = vlc_wrap_cptr( input_item, &input_item_Release );
54 ///
55 /// Wraps a C pointer into a std::unique_ptr
56 ///
57 /// This will convert a C pointer of type T to a std::unique_ptr<T, R> where
58 /// T is the pointee type, and R is an arbitrary releaser type.
59 ///
60 /// ptr will be automatically released by calling r( ptr ) when falling out of
61 /// scope (whether by returning of by throwing an exception
62 ///
63 /// @param ptr a C pointer
64 /// @param r An instance of a Callable type, that will be invoked with ptr
65 /// as its first and only parameter.
66 template <typename T, typename Releaser>
67 inline auto wrap_cptr( T* ptr, Releaser&& r ) noexcept
68 -> std::unique_ptr<T, typename std::decay<decltype( r )>::type>
70 return std::unique_ptr<T, typename std::decay<decltype( r )>::type>{
71 ptr, std::forward<Releaser>( r )
75 ///
76 /// Wraps a C pointer into a std::unique_ptr
77 ///
78 /// This will convert a C pointer to an array of type T to a
79 /// std::unique_ptr<T[], R> where T is the pointee type, and R is an arbitrary
80 /// releaser type.
81 ///
82 /// ptr will be automatically released by calling r( ptr ) when falling out of
83 /// scope (whether by returning of by throwing an exception
84 ///
85 /// This function is equivalent to wrap_cptr, except that the returned
86 /// unique_ptr provides an operator[] for array access instead of operator* and
87 /// operator->
88 ///
89 /// @param ptr a C pointer
90 /// @param r An instance of a Callable type, that will be invoked with ptr
91 /// as its first and only parameter.
92 template <typename T, typename Releaser>
93 inline auto wrap_carray( T* ptr, Releaser&& r ) noexcept
94 -> std::unique_ptr<T[], typename std::decay<decltype( r )>::type>
96 return std::unique_ptr<T[], typename std::decay<decltype( r )>::type>{
97 ptr, std::forward<Releaser>( r )
102 /// Wraps a C pointer into a std::unique_ptr
104 /// This is a convenience wrapper that will use free() as its releaser
106 template <typename T>
107 inline std::unique_ptr<T, void (*)(void*)> wrap_cptr( T* ptr ) noexcept
109 return wrap_cptr( ptr, &free );
113 /// Wraps a C pointer into a std::unique_ptr
115 /// This is a convenience wrapper that will use free() as its releaser
117 template <typename T>
118 inline std::unique_ptr<T[], void (*)(void*)> wrap_carray( T* ptr ) noexcept
120 return wrap_carray( ptr, &free );
123 } // anonymous namespace
126 /// Wraps a C shared resource having associated Hold() and Release() functions
128 /// This is a RAII wrapper for C shared resources (which are manually managed by
129 /// calling explicitly their Hold() and Release() functions).
131 /// The Hold() and Release() functions must accept exactly one parameter having
132 /// type T* (the raw pointer type). Their return type is irrelevant.
134 /// To create a new shared resource wrapper type for my_type_t, simply declare:
136 /// using MyTypePtr =
137 /// vlc_shared_data_ptr_type(my_type_t, my_type_Hold, my_type_Release);
139 /// Then use it to wrap a raw C pointer:
141 /// my_type_t *raw_ptr = /* ... */;
142 /// MyTypePtr ptr(raw_ptr);
144 // In C++17, the template declaration could be replaced by:
145 // template<typename T, auto HOLD, auto RELEASE>
146 template <typename T, typename H, typename R, H HOLD, R RELEASE>
147 class vlc_shared_data_ptr {
148 T *ptr = nullptr;
150 public:
151 /* default implicit constructor */
152 vlc_shared_data_ptr() = default;
155 * Wrap a shared resource.
157 * If the pointer is not nullptr, and hold is true, then the resource is
158 * hold (the caller shared ownership is preserved).
159 * If hold is false, then the caller transfers the ownership to this
160 * wrapper.
162 * \param ptr the raw pointer (can be nullptr)
163 * \param hold whether the resource must be hold
165 explicit vlc_shared_data_ptr(T *ptr, bool hold = true)
166 : ptr(ptr)
168 if (ptr && hold)
169 HOLD(ptr);
172 vlc_shared_data_ptr(const vlc_shared_data_ptr &other)
173 : vlc_shared_data_ptr(other.ptr) {}
175 vlc_shared_data_ptr(vlc_shared_data_ptr &&other) noexcept
176 : ptr(other.ptr)
178 other.ptr = nullptr;
181 ~vlc_shared_data_ptr()
183 if (ptr)
184 RELEASE(ptr);
187 vlc_shared_data_ptr &operator=(const vlc_shared_data_ptr &other)
189 reset(other.ptr, true);
190 return *this;
193 vlc_shared_data_ptr &operator=(vlc_shared_data_ptr &&other) noexcept
195 reset(other.ptr, false);
196 other.ptr = nullptr;
197 return *this;
200 bool operator==(const vlc_shared_data_ptr &other) const
202 return ptr == other.ptr;
205 bool operator!=(const vlc_shared_data_ptr &other) const
207 return !(*this == other);
210 explicit operator bool() const
212 return ptr;
215 T &operator*() const
217 return *ptr;
220 T *operator->() const
222 return ptr;
225 T *get() const
227 return ptr;
231 * Reset the shared resource.
233 * ptr.reset(rawptr, hold);
235 * is semantically equivalent to:
237 * ptr = vlc_shared_data_ptr<...>(rawptr, hold);
239 * If the pointer is not nullptr, and hold is true, then the resource is
240 * hold (the caller shared ownership is preserved).
241 * If hold is false, then the caller transfers the ownership to this
242 * wrapper.
244 * \param ptr the raw pointer (can be nullptr)
245 * \param hold whether the resource must be hold
247 void reset(T *newptr = nullptr, bool hold = true)
249 if (newptr && hold)
250 HOLD(newptr);
251 if (ptr)
252 RELEASE(ptr);
253 ptr = newptr;
257 // useful due to the unnecessarily complex template declaration before C++17
258 #define vlc_shared_data_ptr_type(type, hold, release) \
259 ::vlc::vlc_shared_data_ptr<type, decltype(&hold), decltype(&release), \
260 &hold, &release>
262 #ifdef VLC_THREADS_H_
264 namespace threads
267 class mutex
269 public:
270 mutex() noexcept
272 vlc_mutex_init( &m_mutex );
274 ~mutex()
276 vlc_mutex_destroy( &m_mutex );
279 mutex( const mutex& ) = delete;
280 mutex& operator=( const mutex& ) = delete;
281 mutex( mutex&& ) = delete;
282 mutex& operator=( mutex&& ) = delete;
284 void lock() noexcept
286 vlc_mutex_lock( &m_mutex );
288 void unlock() noexcept
290 vlc_mutex_unlock( &m_mutex );
293 private:
294 vlc_mutex_t m_mutex;
295 friend class condition_variable;
296 friend class mutex_locker;
299 class condition_variable
301 public:
302 condition_variable() noexcept
304 vlc_cond_init( &m_cond );
306 ~condition_variable()
308 vlc_cond_destroy( &m_cond );
310 void signal() noexcept
312 vlc_cond_signal( &m_cond );
314 void broadcast() noexcept
316 vlc_cond_broadcast( &m_cond );
318 void wait( mutex& mutex ) noexcept
320 vlc_cond_wait( &m_cond, &mutex.m_mutex );
322 int timedwait( mutex& mutex, vlc_tick_t deadline ) noexcept
324 return vlc_cond_timedwait( &m_cond, &mutex.m_mutex, deadline );
327 private:
328 vlc_cond_t m_cond;
331 class mutex_locker
333 public:
334 mutex_locker( vlc_mutex_t* m ) noexcept
335 : m_mutex( m )
337 vlc_mutex_lock( m_mutex );
339 mutex_locker( mutex& m ) noexcept
340 : mutex_locker( &m.m_mutex )
343 ~mutex_locker()
345 vlc_mutex_unlock( m_mutex );
347 mutex_locker( const mutex_locker& ) = delete;
348 mutex_locker& operator=( const mutex_locker& ) = delete;
349 mutex_locker( mutex_locker&& ) = delete;
350 mutex_locker& operator=( mutex_locker&& ) = delete;
352 private:
353 vlc_mutex_t* m_mutex;
356 class semaphore
358 public:
359 semaphore() noexcept
361 vlc_sem_init( &m_sem, 0 );
363 semaphore( unsigned int count ) noexcept
365 vlc_sem_init( &m_sem, count );
367 ~semaphore()
369 vlc_sem_destroy( &m_sem );
372 semaphore( const semaphore& ) = delete;
373 semaphore& operator=( const semaphore& ) = delete;
374 semaphore( semaphore&& ) = delete;
375 semaphore& operator=( semaphore&& ) = delete;
377 int post() noexcept
379 return vlc_sem_post( &m_sem );
381 void wait() noexcept
383 vlc_sem_wait( &m_sem );
386 int wait_i11e() noexcept
388 return vlc_sem_wait_i11e( &m_sem );
391 private:
392 vlc_sem_t m_sem;
397 #endif // VLC_THREADS_H_
399 } // namespace vlc
401 #endif
403 #endif // VLC_CXX_HELPERS_HPP