LCOV - code coverage report
Current view: top level - gi - toggle.h (source / functions) Coverage Total Hit
Test: gjs-1.86.0 Code Coverage Lines: 100.0 % 11 11
Test Date: 2025-11-16 18:28:38 Functions: 100.0 % 7 7
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75.0 % 4 3

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
       2                 :             : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
       3                 :             : // SPDX-FileCopyrightText: 2017 Endless Mobile, Inc.
       4                 :             : // SPDX-FileCopyrightText: 2021 Canonical Ltd.
       5                 :             : // SPDX-FileContributor: Authored by: Philip Chimento <philip@endlessm.com>
       6                 :             : // SPDX-FileContributor: Philip Chimento <philip.chimento@gmail.com>
       7                 :             : // SPDX-FileContributor: Marco Trevisan <marco.trevisan@canonical.com>
       8                 :             : 
       9                 :             : #pragma once
      10                 :             : 
      11                 :             : #include <config.h>
      12                 :             : 
      13                 :             : #include <atomic>
      14                 :             : #include <deque>
      15                 :             : #include <thread>
      16                 :             : #include <utility>  // for pair
      17                 :             : 
      18                 :             : #include <glib.h>  // for gboolean
      19                 :             : 
      20                 :             : class ObjectInstance;
      21                 :             : namespace Gjs {
      22                 :             : namespace Test {
      23                 :             : struct ToggleQueue;
      24                 :             : }
      25                 :             : }
      26                 :             : 
      27                 :             : /* Thread-safe queue for enqueueing toggle-up or toggle-down events on GObjects
      28                 :             :  * from any thread. For more information, see object.cpp, comments near
      29                 :             :  * wrapped_gobj_toggle_notify(). */
      30                 :             : class ToggleQueue {
      31                 :             : public:
      32                 :             :     enum Direction {
      33                 :             :         DOWN,
      34                 :             :         UP
      35                 :             :     };
      36                 :             : 
      37                 :             :     using Handler = void (*)(ObjectInstance*, Direction);
      38                 :             : 
      39                 :             :  private:
      40                 :             :     friend Gjs::Test::ToggleQueue;
      41                 :             :     struct Item {
      42                 :             :         Item() {}
      43                 :          62 :         Item(ObjectInstance* o, Direction d) : object(o), direction(d) {}
      44                 :             :         ObjectInstance* object;
      45                 :             :         ToggleQueue::Direction direction;
      46                 :             :     };
      47                 :             : 
      48                 :             :     struct Locked {
      49                 :        9660 :         explicit Locked(ToggleQueue* queue) { queue->lock(); }
      50                 :        9660 :         ~Locked() { get_default_unlocked().maybe_unlock(); }
      51                 :        9608 :         ToggleQueue* operator->() { return &get_default_unlocked(); }
      52                 :             :     };
      53                 :             : 
      54                 :             :     std::deque<Item> q;
      55                 :             :     std::atomic_bool m_shutdown = ATOMIC_VAR_INIT(false);
      56                 :             : 
      57                 :             :     unsigned m_idle_id = 0;
      58                 :             :     Handler m_toggle_handler = nullptr;
      59                 :             :     std::atomic<std::thread::id> m_holder = std::thread::id();
      60                 :             :     unsigned m_holder_ref_count = 0;
      61                 :             : 
      62                 :             :     void lock();
      63                 :             :     void maybe_unlock();
      64                 :             :     [[nodiscard]] bool is_locked() const {
      65                 :             :         return m_holder != std::thread::id();
      66                 :             :     }
      67                 :       19628 :     [[nodiscard]] bool owns_lock() const {
      68                 :       19628 :         return m_holder == std::this_thread::get_id();
      69                 :             :     }
      70                 :             : 
      71                 :             :     [[nodiscard]]
      72                 :             :     std::deque<Item>::iterator find_operation_locked(const ObjectInstance*,
      73                 :             :                                                      Direction);
      74                 :             : 
      75                 :             :     [[nodiscard]]
      76                 :             :     std::deque<Item>::const_iterator find_operation_locked(
      77                 :             :         const ObjectInstance*, Direction) const;
      78                 :             : 
      79                 :             :     static gboolean idle_handle_toggle(void *data);
      80                 :             :     static void idle_destroy_notify(void *data);
      81                 :             : 
      82                 :       28873 :     [[nodiscard]] static ToggleQueue& get_default_unlocked() {
      83   [ +  +  +  - ]:       28873 :         static ToggleQueue the_singleton;
      84                 :       28873 :         return the_singleton;
      85                 :             :     }
      86                 :             : 
      87                 :             :  public:
      88                 :             :     /* These two functions return a pair DOWN, UP signifying whether toggles
      89                 :             :      * are / were queued. is_queued() just checks and does not modify. */
      90                 :             :     [[nodiscard]] std::pair<bool, bool> is_queued(ObjectInstance*) const;
      91                 :             :     // Cancels pending toggles and returns whether any were queued.
      92                 :             :     std::pair<bool, bool> cancel(ObjectInstance*);
      93                 :             : 
      94                 :             :     /* Pops a toggle from the queue and processes it. Call this if you don't
      95                 :             :      * want to wait for it to be processed in idle time. Returns false if queue
      96                 :             :      * is empty. */
      97                 :             :     bool handle_toggle(Handler);
      98                 :             :     void handle_all_toggles(Handler);
      99                 :             : 
     100                 :             :     /* After calling this, the toggle queue won't accept any more toggles. Only
     101                 :             :      * intended for use when destroying the JSContext and breaking the
     102                 :             :      * associations between C and JS objects. */
     103                 :             :     void shutdown();
     104                 :             : 
     105                 :             :     // Queues a toggle to be processed in idle time.
     106                 :             :     void enqueue(ObjectInstance*, Direction, Handler);
     107                 :             : 
     108                 :        9605 :     [[nodiscard]] static Locked get_default() {
     109                 :        9605 :         return Locked(&get_default_unlocked());
     110                 :             :     }
     111                 :             : };
        

Generated by: LCOV version 2.0-1