Coverage Report

Created: 2022-08-24 06:19

/src/Fast-DDS/include/fastrtps/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 _UTILS_TIMEDMUTEX_HPP_
20
#define _UTILS_TIMEDMUTEX_HPP_
21
22
#include <chrono>
23
#include <iostream>
24
25
#if defined(_WIN32)
26
#include <thread>
27
extern int clock_gettime(
28
        int,
29
        struct timespec* tv);
30
#elif _GTHREAD_USE_MUTEX_TIMEDLOCK
31
#include <mutex>
32
#else
33
#include <pthread.h>
34
#endif // if defined(_WIN32)
35
36
namespace eprosima {
37
namespace fastrtps {
38
39
#if defined(_WIN32)
40
class TimedMutex
41
{
42
public:
43
44
    TimedMutex()
45
    {
46
        _Mtx_init(&mutex_, _Mtx_timed);
47
    }
48
49
    TimedMutex(
50
            const TimedMutex&) = delete;
51
    TimedMutex& operator =(
52
            const TimedMutex&) = delete;
53
54
    ~TimedMutex()
55
    {
56
        _Mtx_destroy(mutex_);
57
    }
58
59
    void lock()
60
    {
61
        _Mtx_lock(mutex_);
62
    }
63
64
    void unlock()
65
    {
66
        _Mtx_unlock(mutex_);
67
    }
68
69
    template <class Rep, class Period>
70
    bool try_lock_for(
71
            const std::chrono::duration<Rep, Period>& rel_time)
72
    {
73
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
74
    }
75
76
    template <class Clock, class Duration>
77
    bool try_lock_until(
78
            const std::chrono::time_point<Clock, Duration>& abs_time)
79
    {
80
        std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
81
82
        if (0 < nsecs.count())
83
        {
84
            struct timespec max_wait = {
85
                0, 0
86
            };
87
            clock_gettime(1, &max_wait);
88
            nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
89
            auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
90
            nsecs -= secs;
91
            max_wait.tv_sec += secs.count();
92
            max_wait.tv_nsec = (long)nsecs.count();
93
            return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
94
        }
95
        else
96
        {
97
            return (_Thrd_success == _Mtx_trylock(mutex_));
98
        }
99
    }
100
101
    void* native_handle() noexcept
102
    {
103
        return mutex_;
104
    }
105
106
private:
107
108
    _Mtx_t mutex_;
109
};
110
111
class RecursiveTimedMutex
112
{
113
public:
114
115
    RecursiveTimedMutex()
116
    {
117
        _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive);
118
    }
119
120
    RecursiveTimedMutex(
121
            const TimedMutex&) = delete;
122
    RecursiveTimedMutex& operator =(
123
            const TimedMutex&) = delete;
124
125
    ~RecursiveTimedMutex()
126
    {
127
        _Mtx_destroy(mutex_);
128
    }
129
130
    void lock()
131
    {
132
        _Mtx_lock(mutex_);
133
    }
134
135
    void unlock()
136
    {
137
        _Mtx_unlock(mutex_);
138
    }
139
140
    bool try_lock()
141
    {
142
        return (_Thrd_success == _Mtx_trylock(mutex_));
143
    }
144
145
    template <class Rep, class Period>
146
    bool try_lock_for(
147
            const std::chrono::duration<Rep, Period>& rel_time)
148
    {
149
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
150
    }
151
152
    template <class Clock, class Duration>
153
    bool try_lock_until(
154
            const std::chrono::time_point<Clock, Duration>& abs_time)
155
    {
156
        std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
157
        if (0 < nsecs.count())
158
        {
159
            struct timespec max_wait = {
160
                0, 0
161
            };
162
            clock_gettime(1, &max_wait);
163
            nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
164
            auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
165
            nsecs -= secs;
166
            max_wait.tv_sec += secs.count();
167
            max_wait.tv_nsec = (long)nsecs.count();
168
            return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait));
169
        }
170
        else
171
        {
172
            return (_Thrd_success == _Mtx_trylock(mutex_));
173
        }
174
    }
175
176
    void* native_handle() noexcept
177
    {
178
        return mutex_;
179
    }
180
181
private:
182
183
    _Mtx_t mutex_;
184
};
185
#elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__)
186
using TimedMutex = std::timed_mutex;
187
using RecursiveTimedMutex = std::recursive_timed_mutex;
188
#else
189
class TimedMutex
190
{
191
public:
192
193
    TimedMutex()
194
0
    {
195
0
        pthread_mutex_init(&mutex_, nullptr);
196
0
    }
197
198
    TimedMutex(
199
            const TimedMutex&) = delete;
200
    TimedMutex& operator =(
201
            const TimedMutex&) = delete;
202
203
    ~TimedMutex()
204
0
    {
205
0
        pthread_mutex_destroy(&mutex_);
206
0
    }
207
208
    void lock()
209
0
    {
210
0
        pthread_mutex_lock(&mutex_);
211
0
    }
212
213
    void unlock()
214
0
    {
215
0
        pthread_mutex_unlock(&mutex_);
216
0
    }
217
218
    template <class Rep, class Period>
219
    bool try_lock_for(
220
            const std::chrono::duration<Rep, Period>& rel_time)
221
    {
222
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
223
    }
224
225
    template <class Clock, class Duration>
226
    bool try_lock_until(
227
            const std::chrono::time_point<Clock, Duration>& abs_time)
228
0
    {
229
0
        std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
230
0
        struct timespec max_wait = {
231
0
            0, 0
232
0
        };
233
0
        clock_gettime(CLOCK_REALTIME, &max_wait);
234
0
        nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
235
0
        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
236
0
        nsecs -= secs;
237
0
        max_wait.tv_sec += secs.count();
238
0
        max_wait.tv_nsec = (long)nsecs.count();
239
0
        return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
240
0
    }
241
242
    pthread_mutex_t* native_handle() noexcept
243
0
    {
244
0
        return &mutex_;
245
0
    }
246
247
private:
248
249
    pthread_mutex_t mutex_;
250
};
251
252
class RecursiveTimedMutex
253
{
254
public:
255
256
    RecursiveTimedMutex()
257
0
    {
258
0
        pthread_mutexattr_init(&mutex_attr_);
259
0
        pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE);
260
0
        pthread_mutex_init(&mutex_, &mutex_attr_);
261
0
    }
262
263
    RecursiveTimedMutex(
264
            const RecursiveTimedMutex&) = delete;
265
    RecursiveTimedMutex& operator =(
266
            const RecursiveTimedMutex&) = delete;
267
268
    ~RecursiveTimedMutex()
269
0
    {
270
0
        pthread_mutex_destroy(&mutex_);
271
0
        pthread_mutexattr_destroy(&mutex_attr_);
272
0
    }
273
274
    void lock()
275
0
    {
276
0
        pthread_mutex_lock(&mutex_);
277
0
    }
278
279
    void unlock()
280
0
    {
281
0
        pthread_mutex_unlock(&mutex_);
282
0
    }
283
284
    bool try_lock()
285
0
    {
286
0
        return (0 == pthread_mutex_trylock(&mutex_));
287
0
    }
288
289
    template <class Rep, class Period>
290
    bool try_lock_for(
291
            const std::chrono::duration<Rep, Period>& rel_time)
292
    {
293
        return try_lock_until(std::chrono::steady_clock::now() + rel_time);
294
    }
295
296
    template <class Clock, class Duration>
297
    bool try_lock_until(
298
            const std::chrono::time_point<Clock, Duration>& abs_time)
299
0
    {
300
0
        std::chrono::nanoseconds nsecs = abs_time - std::chrono::steady_clock::now();
301
0
        struct timespec max_wait = {
302
0
            0, 0
303
0
        };
304
0
        clock_gettime(CLOCK_REALTIME, &max_wait);
305
0
        nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec);
306
0
        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
307
0
        nsecs -= secs;
308
0
        max_wait.tv_sec += secs.count();
309
0
        max_wait.tv_nsec = (long)nsecs.count();
310
0
        return (0 == pthread_mutex_timedlock(&mutex_, &max_wait));
311
0
    }
312
313
    pthread_mutex_t* native_handle() noexcept
314
0
    {
315
0
        return &mutex_;
316
0
    }
317
318
private:
319
320
    pthread_mutexattr_t mutex_attr_;
321
322
    pthread_mutex_t mutex_;
323
};
324
325
#endif //_WIN32
326
327
} //namespace fastrtps
328
} //namespace eprosima
329
330
#endif // _UTILS_TIMEDMUTEX_HPP_