EtcPal  0.3.0
ETC Platform Abstraction Layer (EtcPal)
View other versions:
lock.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2020 ETC Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************
16  * This file is a part of EtcPal. For more information, go to:
17  * https://github.com/ETCLabs/EtcPal
18  ******************************************************************************/
19 
22 
23 #ifndef ETCPAL_CPP_LOCK_H_
24 #define ETCPAL_CPP_LOCK_H_
25 
26 #include <stdexcept>
27 #include "etcpal/cpp/common.h"
28 #include "etcpal/lock.h"
29 
30 namespace etcpal
31 {
44 
88 class Mutex
89 {
90 public:
91  Mutex();
92  ~Mutex();
93 
94  Mutex(const Mutex& other) = delete;
95  Mutex& operator=(const Mutex& other) = delete;
96  Mutex(Mutex&& other) = delete;
97  Mutex& operator=(Mutex&& other) = delete;
98 
99  bool Lock();
100  bool TryLock(int timeout_ms = 0);
101  void Unlock();
102 
103  etcpal_mutex_t& get();
104 
105 private:
106  etcpal_mutex_t mutex_{};
107 };
108 
110 inline Mutex::Mutex()
111 {
112  (void)etcpal_mutex_create(&mutex_);
113 }
114 
117 {
118  etcpal_mutex_destroy(&mutex_);
119 }
120 
123 inline bool Mutex::Lock()
124 {
125  return etcpal_mutex_lock(&mutex_);
126 }
127 
139 inline bool Mutex::TryLock(int timeout_ms)
140 {
141  return etcpal_mutex_timed_lock(&mutex_, timeout_ms);
142 }
143 
147 inline void Mutex::Unlock()
148 {
149  etcpal_mutex_unlock(&mutex_);
150 }
151 
154 {
155  return mutex_;
156 }
157 
206 class Signal
207 {
208 public:
209  Signal();
210  ~Signal();
211 
212  Signal(const Signal& other) = delete;
213  Signal& operator=(const Signal& other) = delete;
214  Signal(Signal&& other) = delete;
215  Signal& operator=(Signal&& other) = delete;
216 
217  bool Wait();
218  bool TryWait(int timeout_ms = 0);
219  void Notify();
220  void NotifyFromIsr();
221 
222  etcpal_signal_t& get();
223 
224 private:
225  etcpal_signal_t signal_{};
226 };
227 
230 {
231  (void)etcpal_signal_create(&signal_);
232 }
233 
236 {
237  etcpal_signal_destroy(&signal_);
238 }
239 
242 inline bool Signal::Wait()
243 {
244  return etcpal_signal_wait(&signal_);
245 }
246 
256 inline bool Signal::TryWait(int timeout_ms)
257 {
258  return etcpal_signal_timed_wait(&signal_, timeout_ms);
259 }
260 
264 inline void Signal::Notify()
265 {
266  etcpal_signal_post(&signal_);
267 }
268 
275 {
276  etcpal_signal_post_from_isr(&signal_);
277 }
278 
281 {
282  return signal_;
283 }
284 
351 class RwLock
352 {
353 public:
354  RwLock();
355  ~RwLock();
356 
357  RwLock(const RwLock& other) = delete;
358  RwLock& operator=(const RwLock& other) = delete;
359  RwLock(RwLock&& other) = delete;
360  RwLock& operator=(RwLock&& other) = delete;
361 
362  bool ReadLock();
363  bool TryReadLock(int timeout_ms = 0);
364  void ReadUnlock();
365 
366  bool WriteLock();
367  bool TryWriteLock(int timeout_ms = 0);
368  void WriteUnlock();
369 
370  etcpal_rwlock_t& get();
371 
372 private:
373  etcpal_rwlock_t rwlock_{};
374 };
375 
378 {
379  (void)etcpal_rwlock_create(&rwlock_);
380 }
381 
384 {
385  etcpal_rwlock_destroy(&rwlock_);
386 }
387 
390 inline bool RwLock::ReadLock()
391 {
392  return etcpal_rwlock_readlock(&rwlock_);
393 }
394 
406 inline bool RwLock::TryReadLock(int timeout_ms)
407 {
408  return etcpal_rwlock_timed_readlock(&rwlock_, timeout_ms);
409 }
410 
414 inline void RwLock::ReadUnlock()
415 {
416  etcpal_rwlock_readunlock(&rwlock_);
417 }
418 
421 inline bool RwLock::WriteLock()
422 {
423  return etcpal_rwlock_writelock(&rwlock_);
424 }
425 
437 inline bool RwLock::TryWriteLock(int timeout_ms)
438 {
439  return etcpal_rwlock_timed_writelock(&rwlock_, timeout_ms);
440 }
441 
445 inline void RwLock::WriteUnlock()
446 {
447  etcpal_rwlock_writeunlock(&rwlock_);
448 }
449 
452 {
453  return rwlock_;
454 }
455 
488 {
489 public:
492  static constexpr unsigned int kDefaultMaxCount = 50;
493 
494  Semaphore(unsigned int initial_count = 0, unsigned int max_count = kDefaultMaxCount);
495  ~Semaphore();
496 
497  Semaphore(const Semaphore& other) = delete;
498  Semaphore& operator=(const Semaphore& other) = delete;
499  Semaphore(Semaphore&& other) = delete;
500  Semaphore& operator=(Semaphore&& other) = delete;
501 
502  bool Wait();
503  bool TryWait(int timeout_ms = 0);
504  bool Post();
505  bool PostFromIsr();
506 
507  etcpal_sem_t& get();
508 
509 private:
510  etcpal_sem_t sem_{};
511 };
512 
514 inline Semaphore::Semaphore(unsigned int initial_count, unsigned int max_count)
515 {
516  (void)etcpal_sem_create(&sem_, initial_count, max_count);
517 }
518 
521 {
522  etcpal_sem_destroy(&sem_);
523 }
524 
527 inline bool Semaphore::Wait()
528 {
529  return etcpal_sem_wait(&sem_);
530 }
531 
541 inline bool Semaphore::TryWait(int timeout_ms)
542 {
543  return etcpal_sem_timed_wait(&sem_, timeout_ms);
544 }
545 
549 inline bool Semaphore::Post()
550 {
551  return etcpal_sem_post(&sem_);
552 }
553 
560 {
561  return etcpal_sem_post_from_isr(&sem_);
562 }
563 
566 {
567  return sem_;
568 }
569 
573 
590 {
591 public:
592  explicit MutexGuard(Mutex& mutex);
593  explicit MutexGuard(etcpal_mutex_t& mutex);
594  ~MutexGuard();
595 
596  MutexGuard(const MutexGuard& other) = delete;
597  MutexGuard& operator=(const MutexGuard& other) = delete;
598  MutexGuard(MutexGuard&& other) = delete;
599  MutexGuard& operator=(MutexGuard&& other) = delete;
600 
601 private:
602  etcpal_mutex_t& mutex_;
603 
604  void GetLock();
605 };
606 
609 inline MutexGuard::MutexGuard(Mutex& mutex) : mutex_(mutex.get())
610 {
611  GetLock();
612 }
613 
616 inline MutexGuard::MutexGuard(etcpal_mutex_t& mutex) : mutex_(mutex)
617 {
618  GetLock();
619 }
620 
623 {
624  etcpal_mutex_unlock(&mutex_);
625 }
626 
627 inline void MutexGuard::GetLock()
628 {
629  if (!etcpal_mutex_lock(&mutex_))
630  ETCPAL_THROW(std::runtime_error("etcpal_mutex_lock failed."));
631 }
632 
649 {
650 public:
651  explicit ReadGuard(RwLock& rwlock);
652  explicit ReadGuard(etcpal_rwlock_t& rwlock);
653  ~ReadGuard();
654 
655  ReadGuard(const ReadGuard& other) = delete;
656  ReadGuard& operator=(const ReadGuard& other) = delete;
657  ReadGuard(ReadGuard&& other) = delete;
658  ReadGuard& operator=(ReadGuard&& other) = delete;
659 
660 private:
661  etcpal_rwlock_t& rwlock_;
662 
663  void GetReadLock();
664 };
665 
668 inline ReadGuard::ReadGuard(RwLock& rwlock) : rwlock_(rwlock.get())
669 {
670  GetReadLock();
671 }
672 
675 inline ReadGuard::ReadGuard(etcpal_rwlock_t& rwlock) : rwlock_(rwlock)
676 {
677  GetReadLock();
678 }
679 
682 {
683  etcpal_rwlock_readunlock(&rwlock_);
684 }
685 
686 inline void ReadGuard::GetReadLock()
687 {
688  if (!etcpal_rwlock_readlock(&rwlock_))
689  ETCPAL_THROW(std::runtime_error("etcpal_rwlock_readlock failed."));
690 }
691 
708 {
709 public:
710  explicit WriteGuard(RwLock& rwlock);
711  explicit WriteGuard(etcpal_rwlock_t& rwlock);
712  ~WriteGuard();
713 
714  WriteGuard(const WriteGuard& other) = delete;
715  WriteGuard& operator=(const WriteGuard& other) = delete;
716  WriteGuard(WriteGuard&& other) = delete;
717  WriteGuard& operator=(WriteGuard&& other) = delete;
718 
719 private:
720  etcpal_rwlock_t& rwlock_;
721 
722  void GetWriteLock();
723 };
724 
727 inline WriteGuard::WriteGuard(RwLock& rwlock) : rwlock_(rwlock.get())
728 {
729  GetWriteLock();
730 }
731 
734 inline WriteGuard::WriteGuard(etcpal_rwlock_t& rwlock) : rwlock_(rwlock)
735 {
736  GetWriteLock();
737 }
738 
741 {
742  etcpal_rwlock_writeunlock(&rwlock_);
743 }
744 
745 inline void WriteGuard::GetWriteLock()
746 {
747  if (!etcpal_rwlock_writelock(&rwlock_))
748  ETCPAL_THROW(std::runtime_error("etcpal_rwlock_writelock failed."));
749 }
750 
752 
753 }; // namespace etcpal
754 
755 #endif // ETCPAL_CPP_LOCK_H_
Lock guard around a mutex.
Definition: lock.h:590
~MutexGuard()
Release the lock upon going out-of-scope.
Definition: lock.h:622
MutexGuard(Mutex &mutex)
Lock an etcpal::Mutex.
Definition: lock.h:609
A wrapper class for the EtcPal mutex type.
Definition: lock.h:89
~Mutex()
Destroy the mutex.
Definition: lock.h:116
Mutex()
Create a new mutex.
Definition: lock.h:110
bool Lock()
Lock the mutex.
Definition: lock.h:123
bool TryLock(int timeout_ms=0)
Attempt to lock the mutex.
Definition: lock.h:139
void Unlock()
Unlock the mutex.
Definition: lock.h:147
etcpal_mutex_t & get()
Get a reference to the underlying etcpal_mutex_t type.
Definition: lock.h:153
Read lock guard around a read-write lock.
Definition: lock.h:649
ReadGuard(RwLock &rwlock)
Lock an etcpal::RwLock for reading.
Definition: lock.h:668
~ReadGuard()
Release the read lock upon going out-of-scope.
Definition: lock.h:681
A wrapper class for the EtcPal read-write lock type.
Definition: lock.h:352
bool WriteLock()
Access the read-write lock for writing.
Definition: lock.h:421
etcpal_rwlock_t & get()
Get a reference to the underlying etcpal_rwlock_t type.
Definition: lock.h:451
void ReadUnlock()
Release a read lock on the read-write lock.
Definition: lock.h:414
~RwLock()
Destroy the read-write lock.
Definition: lock.h:383
void WriteUnlock()
Release a write lock on the read-write lock.
Definition: lock.h:445
bool TryReadLock(int timeout_ms=0)
Try to access the read-write lock for reading.
Definition: lock.h:406
RwLock()
Create a new read-write lock.
Definition: lock.h:377
bool TryWriteLock(int timeout_ms=0)
Try to access the read-write lock for writing.
Definition: lock.h:437
bool ReadLock()
Access the read-write lock for reading.
Definition: lock.h:390
A wrapper class for the EtcPal counting semaphore type.
Definition: lock.h:488
static constexpr unsigned int kDefaultMaxCount
The default value used for the semaphore's max_count.
Definition: lock.h:492
etcpal_sem_t & get()
Get a reference to the underlying etcpal_sem_t type.
Definition: lock.h:565
bool PostFromIsr()
Post the semaphore from an interrupt context.
Definition: lock.h:559
~Semaphore()
Destroy the semaphore.
Definition: lock.h:520
bool Post()
Post the semaphore.
Definition: lock.h:549
Semaphore(unsigned int initial_count=0, unsigned int max_count=kDefaultMaxCount)
Create a new semaphore.
Definition: lock.h:514
bool TryWait(int timeout_ms=0)
Wait for the semaphore until either it is received or a timeout expires.
Definition: lock.h:541
bool Wait()
Wait for the semaphore.
Definition: lock.h:527
A wrapper class for the EtcPal signal type.
Definition: lock.h:207
~Signal()
Destroy the signal.
Definition: lock.h:235
Signal()
Create a new signal.
Definition: lock.h:229
etcpal_signal_t & get()
Get a reference to the underlying etcpal_signal_t type.
Definition: lock.h:280
void Notify()
Notify those waiting on the signal.
Definition: lock.h:264
bool TryWait(int timeout_ms=0)
Wait for the signal until either it is received or a timeout expires.
Definition: lock.h:256
void NotifyFromIsr()
Notify those waiting on the signal from an interrupt context.
Definition: lock.h:274
bool Wait()
Wait for the signal.
Definition: lock.h:242
Write lock guard around a read-write lock.
Definition: lock.h:708
WriteGuard(RwLock &rwlock)
Lock an etcpal::RwLock for writing.
Definition: lock.h:727
~WriteGuard()
Release the write lock upon going out-of-scope.
Definition: lock.h:740
Common definitions used by EtcPal C++ wrappers.
void etcpal_mutex_destroy(etcpal_mutex_t *id)
Destroy a mutex object.
PLATFORM_DEFINED etcpal_mutex_t
The mutex identifier.
Definition: lock.dox:93
void etcpal_mutex_unlock(etcpal_mutex_t *id)
Unlock a mutex.
bool etcpal_mutex_create(etcpal_mutex_t *id)
Create a new mutex.
bool etcpal_mutex_timed_lock(etcpal_mutex_t *id, int timeout_ms)
Try to lock a mutex, giving up after a timeout.
bool etcpal_mutex_lock(etcpal_mutex_t *id)
Lock a mutex.
bool etcpal_rwlock_timed_writelock(etcpal_rwlock_t *id, int timeout_ms)
Try to access a read-write lock for writing, giving up after a timeout.
void etcpal_rwlock_destroy(etcpal_rwlock_t *id)
Destroy a read-write lock object.
void etcpal_rwlock_readunlock(etcpal_rwlock_t *id)
Release a read lock on a read-write lock object.
PLATFORM_DEFINED etcpal_rwlock_t
The read-write lock identifier.
Definition: lock.dox:417
bool etcpal_rwlock_create(etcpal_rwlock_t *id)
Create a new read-write lock.
void etcpal_rwlock_writeunlock(etcpal_rwlock_t *id)
Release a write lock on a read-write lock object.
bool etcpal_rwlock_readlock(etcpal_rwlock_t *id)
Access a read-write lock for reading.
bool etcpal_rwlock_writelock(etcpal_rwlock_t *id)
Access a read-write lock for writing.
bool etcpal_rwlock_timed_readlock(etcpal_rwlock_t *id, int timeout_ms)
Try to access a read-write lock for reading, giving up after a timeout.
bool etcpal_sem_create(etcpal_sem_t *id, unsigned int initial_count, unsigned int max_count)
Create a new counting semaphore.
PLATFORM_DEFINED etcpal_sem_t
The semaphore identifier.
Definition: lock.dox:610
bool etcpal_sem_post(etcpal_sem_t *id)
Post a semaphore.
void etcpal_sem_destroy(etcpal_sem_t *id)
Destroy a semaphore object.
bool etcpal_sem_post_from_isr(etcpal_sem_t *id)
Post a semaphore from an interrupt context.
bool etcpal_sem_timed_wait(etcpal_sem_t *id, int timeout_ms)
Wait for a semaphore, giving up after a timeout.
bool etcpal_sem_wait(etcpal_sem_t *id)
Wait for a semaphore.
bool etcpal_signal_wait(etcpal_signal_t *id)
Wait for a signal.
bool etcpal_signal_create(etcpal_signal_t *id)
Create a new signal.
void etcpal_signal_destroy(etcpal_signal_t *id)
Destroy a signal object.
bool etcpal_signal_timed_wait(etcpal_signal_t *id, int timeout_ms)
Wait for a signal, giving up after a timeout.
PLATFORM_DEFINED etcpal_signal_t
The signal identifier.
Definition: lock.dox:243
void etcpal_signal_post_from_isr(etcpal_signal_t *id)
Post a signal from an interrupt context.
void etcpal_signal_post(etcpal_signal_t *id)
Post a signal.