Coverage Report

Created: 2025-06-13 06:45

/src/Fast-DDS/include/fastdds/utils/TimedMutex.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
 * @file TimedMutex.hpp
17
 */
18
19
#ifndef FASTDDS_UTILS__TIMEDMUTEX_HPP
20
#define FASTDDS_UTILS__TIMEDMUTEX_HPP
21
22
#include <chrono>
23
#include <iostream>
24
25
#if defined(_WIN32)
26
27
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
28
#include <mutex>
29
#elif defined(MINGW_COMPILER)
30
#include <mutex>
31
#else
32
#include <thread>
33
extern int clock_gettime(
34
        int,
35
        struct timespec* tv);
36
#endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
37
38
#elif _GTHREAD_USE_MUTEX_TIMEDLOCK
39
#include <mutex>
40
#else
41
#include <pthread.h>
42
#endif // if defined(_WIN32)
43
44
namespace eprosima {
45
namespace fastdds {
46
47
#if defined(_WIN32)
48
49
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
50
using TimedMutex = std::timed_mutex;
51
using RecursiveTimedMutex = std::recursive_timed_mutex;
52
#elif defined(MINGW_COMPILER)
53
using TimedMutex = std::timed_mutex;
54
using RecursiveTimedMutex = std::recursive_timed_mutex;
55
#else
56
class TimedMutex
57
{
58
59
public:
60
61
    TimedMutex()
62
    {
63
        _Mtx_init(&mutex_, _Mtx_timed);
64
    }
65
66
    TimedMutex(
67
            const TimedMutex&) = delete;
68
    TimedMutex& operator =(
69
            const TimedMutex&) = delete;
70
71
    ~TimedMutex()
72
    {
73
        _Mtx_destroy(mutex_);
74
    }
75
76
    void lock()
77
    {
78
        _Mtx_lock(mutex_);
79
    }
80
81
    void unlock()
82
    {
83
        _Mtx_unlock(mutex_);
84
    }
85
86
    template <class Rep, class Period>
87
    bool try_lock_for(
88
            const std::chrono::duration<Rep, Period>& rel_time)
89
    {
90
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
91
    }
92
93
    template <class Clock, class Duration>
94
    bool try_lock_until(
95
            const std::chrono::time_point<Clock, Duration>& abs_time)
96
    {
97
        std::chrono::nanoseconds nsecs = abs_time - Clock::now();
98
99
        if (0 < nsecs.count())
100
        {
101
            struct timespec max_wait = {
102
                0, 0
103
            };
104
            clock_gettime(1, &max_wait);
105
            nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
106
            auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
107
            nsecs -= secs;
108
            max_wait.tv_sec += secs.count();
109
            max_wait.tv_nsec = (long)nsecs.count();
110
            return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
111
        }
112
        else
113
        {
114
            return (_Thrd_success == _Mtx_trylock(mutex_));
115
        }
116
    }
117
118
    void* native_handle() noexcept
119
    {
120
        return mutex_;
121
    }
122
123
private:
124
125
    _Mtx_t mutex_;
126
};
127
128
class RecursiveTimedMutex
129
{
130
public:
131
132
    RecursiveTimedMutex()
133
    {
134
        _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
135
    }
136
137
    RecursiveTimedMutex(
138
            const TimedMutex&) = delete;
139
    RecursiveTimedMutex& operator =(
140
            const TimedMutex&) = delete;
141
142
    ~RecursiveTimedMutex()
143
    {
144
        _Mtx_destroy(mutex_);
145
    }
146
147
    void lock()
148
    {
149
        _Mtx_lock(mutex_);
150
    }
151
152
    void unlock()
153
    {
154
        _Mtx_unlock(mutex_);
155
    }
156
157
    bool try_lock()
158
    {
159
        return (_Thrd_success == _Mtx_trylock(mutex_));
160
    }
161
162
    template <class Rep, class Period>
163
    bool try_lock_for(
164
            const std::chrono::duration<Rep, Period>& rel_time)
165
    {
166
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
167
    }
168
169
    template <class Clock, class Duration>
170
    bool try_lock_until(
171
            const std::chrono::time_point<Clock, Duration>& abs_time)
172
    {
173
        std::chrono::nanoseconds nsecs = abs_time - Clock::now();
174
        if (0 < nsecs.count())
175
        {
176
            struct timespec max_wait = {
177
                0, 0
178
            };
179
            clock_gettime(1, &max_wait);
180
            nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
181
            auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
182
            nsecs -= secs;
183
            max_wait.tv_sec += secs.count();
184
            max_wait.tv_nsec = (long)nsecs.count();
185
            return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
186
        }
187
        else
188
        {
189
            return (_Thrd_success == _Mtx_trylock(mutex_));
190
        }
191
    }
192
193
    void* native_handle() noexcept
194
    {
195
        return mutex_;
196
    }
197
198
private:
199
200
    _Mtx_t mutex_;
201
};
202
#endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528
203
204
#elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__)
205
using TimedMutex = std::timed_mutex;
206
using RecursiveTimedMutex = std::recursive_timed_mutex;
207
#else
208
class TimedMutex
209
{
210
public:
211
212
    TimedMutex()
213
0
    {
214
0
        pthread_mutex_init(&mutex_, nullptr);
215
0
    }
216
217
    TimedMutex(
218
            const TimedMutex&) = delete;
219
    TimedMutex& operator =(
220
            const TimedMutex&) = delete;
221
222
    ~TimedMutex()
223
0
    {
224
0
        pthread_mutex_destroy(&mutex_);
225
0
    }
226
227
    void lock()
228
0
    {
229
0
        pthread_mutex_lock(&mutex_);
230
0
    }
231
232
    void unlock()
233
0
    {
234
0
        pthread_mutex_unlock(&mutex_);
235
0
    }
236
237
    template <class Rep, class Period>
238
    bool try_lock_for(
239
            const std::chrono::duration<Rep, Period>& rel_time)
240
    {
241
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
242
    }
243
244
    template <class Clock, class Duration>
245
    bool try_lock_until(
246
            const std::chrono::time_point<Clock, Duration>& abs_time)
247
    {
248
        std::chrono::nanoseconds nsecs = abs_time - Clock::now();
249
        struct timespec max_wait = {
250
            0, 0
251
        };
252
        clock_gettime(CLOCK_REALTIME, &max_wait);
253
        nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
254
        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
255
        nsecs -= secs;
256
        max_wait.tv_sec += secs.count();
257
        max_wait.tv_nsec = (long)nsecs.count();
258
        return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
259
    }
260
261
    pthread_mutex_t* native_handle() noexcept
262
0
    {
263
0
        return &mutex_;
264
0
    }
265
266
private:
267
268
    pthread_mutex_t mutex_;
269
};
270
271
class RecursiveTimedMutex
272
{
273
public:
274
275
    RecursiveTimedMutex()
276
0
    {
277
0
        pthread_mutexattr_init(&mutex_attr_);
278
0
        pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
279
0
        pthread_mutex_init(&mutex_, &mutex_attr_);
280
0
    }
281
282
    RecursiveTimedMutex(
283
            const RecursiveTimedMutex&) = delete;
284
    RecursiveTimedMutex& operator =(
285
            const RecursiveTimedMutex&) = delete;
286
287
    ~RecursiveTimedMutex()
288
0
    {
289
0
        pthread_mutex_destroy(&mutex_);
290
0
        pthread_mutexattr_destroy(&mutex_attr_);
291
0
    }
292
293
    void lock()
294
0
    {
295
0
        pthread_mutex_lock(&mutex_);
296
0
    }
297
298
    void unlock()
299
0
    {
300
0
        pthread_mutex_unlock(&mutex_);
301
0
    }
302
303
    bool try_lock()
304
0
    {
305
0
        return (0 == pthread_mutex_trylock(&mutex_));
306
0
    }
307
308
    template <class Rep, class Period>
309
    bool try_lock_for(
310
            const std::chrono::duration<Rep, Period>& rel_time)
311
    {
312
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
313
    }
314
315
    template <class Clock, class Duration>
316
    bool try_lock_until(
317
            const std::chrono::time_point<Clock, Duration>& abs_time)
318
    {
319
        std::chrono::nanoseconds nsecs = abs_time - Clock::now();
320
        struct timespec max_wait = {
321
            0, 0
322
        };
323
        clock_gettime(CLOCK_REALTIME, &max_wait);
324
        nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
325
        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
326
        nsecs -= secs;
327
        max_wait.tv_sec += secs.count();
328
        max_wait.tv_nsec = (long)nsecs.count();
329
        return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
330
    }
331
332
    pthread_mutex_t* native_handle() noexcept
333
0
    {
334
0
        return &mutex_;
335
0
    }
336
337
private:
338
339
    pthread_mutexattr_t mutex_attr_;
340
341
    pthread_mutex_t mutex_;
342
};
343
344
#endif //_WIN32
345
346
} //namespace fastdds
347
} //namespace eprosima
348
349
#endif // FASTDDS_UTILS__TIMEDMUTEX_HPP