Coverage Report

Created: 2025-07-11 06:23

/src/libzmq/src/dbuffer.hpp
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: MPL-2.0 */
2
3
#ifndef __ZMQ_DBUFFER_HPP_INCLUDED__
4
#define __ZMQ_DBUFFER_HPP_INCLUDED__
5
6
#include <stdlib.h>
7
#include <stddef.h>
8
#include <algorithm>
9
10
#include "mutex.hpp"
11
#include "msg.hpp"
12
13
namespace zmq
14
{
15
//  dbuffer is a single-producer single-consumer double-buffer
16
//  implementation.
17
//
18
//  The producer writes to a back buffer and then tries to swap
19
//  pointers between the back and front buffers. If it fails,
20
//  due to the consumer reading from the front buffer, it just
21
//  gives up, which is ok since writes are many and redundant.
22
//
23
//  The reader simply reads from the front buffer.
24
//
25
//  has_msg keeps track of whether there has been a not yet read
26
//  value written, it is used by ypipe_conflate to mimic ypipe
27
//  functionality regarding a reader being asleep
28
29
template <typename T> class dbuffer_t;
30
31
template <> class dbuffer_t<msg_t>
32
{
33
  public:
34
0
    dbuffer_t () : _back (&_storage[0]), _front (&_storage[1]), _has_msg (false)
35
0
    {
36
0
        _back->init ();
37
0
        _front->init ();
38
0
    }
39
40
    ~dbuffer_t ()
41
0
    {
42
0
        _back->close ();
43
0
        _front->close ();
44
0
    }
45
46
    void write (const msg_t &value_)
47
0
    {
48
0
        zmq_assert (value_.check ());
49
0
        *_back = value_;
50
51
0
        zmq_assert (_back->check ());
52
53
0
        if (_sync.try_lock ()) {
54
0
            _front->move (*_back);
55
0
            _has_msg = true;
56
57
0
            _sync.unlock ();
58
0
        }
59
0
    }
60
61
    bool read (msg_t *value_)
62
0
    {
63
0
        if (!value_)
64
0
            return false;
65
66
0
        {
67
0
            scoped_lock_t lock (_sync);
68
0
            if (!_has_msg)
69
0
                return false;
70
71
0
            zmq_assert (_front->check ());
72
73
0
            *value_ = *_front;
74
0
            _front->init (); // avoid double free
75
76
0
            _has_msg = false;
77
0
            return true;
78
0
        }
79
0
    }
80
81
82
    bool check_read ()
83
0
    {
84
0
        scoped_lock_t lock (_sync);
85
86
0
        return _has_msg;
87
0
    }
88
89
    bool probe (bool (*fn_) (const msg_t &))
90
0
    {
91
0
        scoped_lock_t lock (_sync);
92
0
        return (*fn_) (*_front);
93
0
    }
94
95
96
  private:
97
    msg_t _storage[2];
98
    msg_t *_back, *_front;
99
100
    mutex_t _sync;
101
    bool _has_msg;
102
103
    ZMQ_NON_COPYABLE_NOR_MOVABLE (dbuffer_t)
104
};
105
}
106
107
#endif