LCOV - code coverage report
Current view: top level - src/base - semaphore.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 45 45 100.0 %
Date: 2026-06-27 19:56:04 Functions: 8 8 100.0 %
Branches: 19 22 86.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2026 by Thun Lu. All rights reserved.
       3                 :            :  * Author: Thun Lu <thun.lu@zohomail.cn>
       4                 :            :  * Repo:   https://github.com/thun-res/vlink
       5                 :            :  *  _    __   __      _           __
       6                 :            :  * | |  / /  / /     (_) ____    / /__
       7                 :            :  * | | / /  / /     / / / __ \  / //_/
       8                 :            :  * | |/ /  / /___  / / / / / / / ,<
       9                 :            :  * |___/  /_____/ /_/ /_/ /_/ /_/|_|
      10                 :            :  *
      11                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
      12                 :            :  * you may not use this file except in compliance with the License.
      13                 :            :  * You may obtain a copy of the License at
      14                 :            :  *
      15                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      16                 :            :  *
      17                 :            :  * Unless required by applicable law or agreed to in writing, software
      18                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      19                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      20                 :            :  * See the License for the specific language governing permissions and
      21                 :            :  * limitations under the License.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "./base/semaphore.h"
      25                 :            : 
      26                 :            : #include <chrono>
      27                 :            : #include <mutex>
      28                 :            : 
      29                 :            : #include "./base/condition_variable.h"
      30                 :            : 
      31                 :            : namespace vlink {
      32                 :            : 
      33                 :            : // Semaphore::Impl
      34                 :            : struct Semaphore::Impl final {
      35                 :            :   mutable std::mutex mtx;
      36                 :            :   ConditionVariable cv;
      37                 :            :   size_t count{0};
      38                 :            :   size_t initial_count{0};
      39                 :            :   size_t in_flight_count{0};
      40                 :            :   bool quit_flag{false};
      41                 :            : };
      42                 :            : 
      43                 :            : // Semaphore
      44                 :         19 : Semaphore::Semaphore(size_t count) noexcept : impl_(std::make_unique<Impl>()) {
      45                 :         19 :   impl_->count = count;
      46                 :         19 :   impl_->initial_count = count;
      47                 :         19 : }
      48                 :            : 
      49                 :         19 : Semaphore::~Semaphore() noexcept {
      50                 :         19 :   std::unique_lock lock(impl_->mtx);
      51                 :         19 :   impl_->quit_flag = true;
      52                 :         19 :   impl_->cv.notify_all();
      53                 :         38 :   impl_->cv.wait(lock, [this]() -> bool { return impl_->in_flight_count == 0; });
      54                 :         19 : }
      55                 :            : 
      56                 :         24 : bool Semaphore::acquire(size_t n, int timeout_ms) noexcept {
      57                 :         24 :   std::unique_lock lock(impl_->mtx);
      58                 :         24 :   ++impl_->in_flight_count;
      59                 :            : 
      60   [ +  +  +  + ]:         40 :   auto predicate = [this, n] { return impl_->count >= n || impl_->quit_flag; };
      61                 :            : 
      62                 :            :   bool acquired;
      63                 :            : 
      64         [ +  + ]:         24 :   if (timeout_ms < 0) {
      65                 :         18 :     impl_->cv.wait(lock, predicate);
      66                 :         18 :     acquired = (impl_->count >= n);
      67                 :            :   } else {
      68   [ +  +  +  - ]:          6 :     acquired = impl_->cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), predicate) && (impl_->count >= n);
      69                 :            :   }
      70                 :            : 
      71                 :            :   bool result;
      72                 :            : 
      73         [ +  + ]:         24 :   if VUNLIKELY (impl_->quit_flag) {
      74                 :          4 :     result = false;
      75                 :            :   } else {
      76         [ +  + ]:         20 :     if (acquired) {
      77                 :         17 :       impl_->count -= n;
      78                 :            :     }
      79                 :            : 
      80                 :         20 :     result = acquired;
      81                 :            :   }
      82                 :            : 
      83         [ +  + ]:         24 :   if (--impl_->in_flight_count == 0) {
      84                 :         19 :     impl_->cv.notify_all();
      85                 :            :   }
      86                 :            : 
      87                 :         48 :   return result;
      88                 :         24 : }
      89                 :            : 
      90                 :         11 : void Semaphore::release(size_t n) noexcept {
      91                 :            :   {
      92                 :         11 :     std::lock_guard lock(impl_->mtx);
      93                 :         11 :     impl_->count += n;
      94                 :         11 :   }
      95                 :            : 
      96                 :         11 :   impl_->cv.notify_all();
      97                 :         11 : }
      98                 :            : 
      99                 :          6 : void Semaphore::reset(bool interrupt_waiters) noexcept {
     100                 :            :   {
     101                 :          6 :     std::lock_guard lock(impl_->mtx);
     102                 :          6 :     impl_->count = impl_->initial_count;
     103                 :          6 :     impl_->quit_flag = interrupt_waiters;
     104                 :          6 :   }
     105                 :            : 
     106   [ +  +  +  -  :          6 :   if (interrupt_waiters || impl_->initial_count > 0) {
                   +  - ]
     107                 :          6 :     impl_->cv.notify_all();
     108                 :            :   }
     109                 :          6 : }
     110                 :            : 
     111                 :         25 : size_t Semaphore::get_count() const noexcept {
     112                 :         25 :   std::lock_guard lock(impl_->mtx);
     113                 :            : 
     114                 :         25 :   return impl_->count;
     115                 :         25 : }
     116                 :            : 
     117                 :            : }  // namespace vlink

Generated by: LCOV version 1.14