aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/util/guard.h
blob: efd7b8345c9fec706aa8e247c5efeec02a8c2c5e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include <cstdio>
#include <unistd.h>

namespace vespalib {

/**
 * @brief A FilePointer wraps a bald FILE pointer inside a guarding
 * object.
 *
 * The underlying file is closed when the FilePointer object is
 * destructed.
 **/
class FilePointer
{
private:
    FILE *_fp;
public:
    /**
     * @brief Create a FilePointer from a FILE pointer.
     *
     * @param file the underlying FILE pointer
     **/
    explicit FilePointer(FILE *file = nullptr) noexcept : _fp(file) {}
    FilePointer(const FilePointer &) = delete;
    FilePointer &operator=(const FilePointer &) = delete;
    /**
     * @brief Close the file if it is still open.
     **/
    ~FilePointer() { reset(); }
    /**
     * @brief Check whether we have a FILE pointer (not nullptr)
     *
     * @return true if we have an underlying FILE pointer
     **/
    bool valid() const noexcept { return (_fp != nullptr); }
    /**
     * @brief Obtain the internal FILE pointer
     *
     * @return internal FILE pointer
     **/
    FILE *fp() const noexcept { return _fp; }
    /**
     * @brief Implicit cast to obtain internal FILE pointer
     *
     * @return internal FILE pointer
     **/
    operator FILE*() noexcept { return _fp; }
    /**
     * @brief Take ownership of a new FILE pointer.
     *
     * The previously owned FILE pointer is closed, if present.
     **/
    void reset(FILE *file = nullptr) {
        if (valid()) {
            fclose(_fp);
        }
        _fp = file;
    }
    /**
     * @brief Release ownership of the current FILE pointer.
     *
     * The file will no longer be closed by the destructor.
     *
     * @return the released FILE pointer
     **/
    FILE *release() noexcept {
        FILE *tmp = _fp;
        _fp = nullptr;
        return tmp;
    }
};

/**
 * @brief A FileDescriptor wraps a file descriptor inside a guarding object.
 *
 * The underlying file is closed when the FileDescriptor object is
 * destructed.
 **/
class FileDescriptor
{
private:
    int _fd;
public:
    /**
     * @brief Create a FileDescriptor from a file descriptor.
     *
     * @param file the underlying file descriptor
     **/
    explicit FileDescriptor(int file = -1) noexcept : _fd(file) {}
    FileDescriptor(const FileDescriptor &) = delete;
    FileDescriptor &operator=(const FileDescriptor &) = delete;
    /**
     * @brief Close the file if it is still open.
     **/
    ~FileDescriptor() { reset(); }
    /**
     * @brief Check whether we have a file descriptor (not -1)
     *
     * @return true if we have an underlying file descriptor
     **/
    bool valid() const noexcept { return (_fd >= 0); }
    /**
     * @brief Obtain the internal file descriptor
     *
     * @return internal file descriptor
     **/
    int fd() const noexcept { return _fd; }
    /**
     * @brief Take ownership of a new file descriptor.
     *
     * The previously owned file descriptor is closed, if present.
     **/
    void reset(int file = -1) {
        if (valid()) {
            close(_fd);
        }
        _fd = file;
    }
    /**
     * @brief Release ownership of the current file descriptor.
     *
     * The file will no longer be closed by the destructor.
     *
     * @return the released file descriptor
     **/
    int release() noexcept {
        int tmp = _fd;
        _fd = -1;
        return tmp;
    }
};


/**
 * @brief A CounterGuard increases an int in the constructor and decreases
 * it in the destructor.
 *
 * This is typically used to keep track of how many threads are inside
 * a given scope at a given time (for example, how many threads that
 * are currently waiting for a specific signal on a monitor).
 **/
class CounterGuard
{
private:
    int &_cnt;
public:
    /**
     * @brief Increase the value
     *
     * @param cnt a reference to the value that will be modified
     **/
    explicit CounterGuard(int &cnt) noexcept : _cnt(cnt) { ++cnt; }
    CounterGuard(const CounterGuard &) = delete;
    CounterGuard &operator=(const CounterGuard &) = delete;
    /**
     * @brief Decrease the value
     **/
    ~CounterGuard() { --_cnt; }
};

} // namespace vespalib