unique_fd.h revision 2a7b86337f7b149887588e4df532272abe3e931c
1/*
2 * Copyright (C) 2015 The Android Open Source Project
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
17#ifndef ANDROID_BASE_UNIQUE_FD_H
18#define ANDROID_BASE_UNIQUE_FD_H
19
20#include <unistd.h>
21
22// DO NOT INCLUDE OTHER LIBBASE HEADERS!
23// This file gets used in libbinder, and libbinder is used everywhere.
24// Including other headers from libbase frequently results in inclusion of
25// android-base/macros.h, which causes macro collisions.
26
27// Container for a file descriptor that automatically closes the descriptor as
28// it goes out of scope.
29//
30//      unique_fd ufd(open("/some/path", "r"));
31//      if (ufd.get() == -1) return error;
32//
33//      // Do something useful, possibly including 'return'.
34//
35//      return 0; // Descriptor is closed for you.
36//
37// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
38// you find this class if you're searching for one of those names.
39namespace android {
40namespace base {
41
42class unique_fd final {
43 public:
44  unique_fd() : value_(-1) {}
45
46  explicit unique_fd(int value) : value_(value) {}
47  ~unique_fd() { clear(); }
48
49  unique_fd(unique_fd&& other) : value_(other.release()) {}
50  unique_fd& operator=(unique_fd&& s) {
51    reset(s.release());
52    return *this;
53  }
54
55  void reset(int new_value) {
56    if (value_ != -1) {
57      // Even if close(2) fails with EINTR, the fd will have been closed.
58      // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
59      // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
60      close(value_);
61    }
62    value_ = new_value;
63  }
64
65  void clear() {
66    reset(-1);
67  }
68
69  int get() const { return value_; }
70  operator int() const { return get(); }
71
72  int release() __attribute__((warn_unused_result)) {
73    int ret = value_;
74    value_ = -1;
75    return ret;
76  }
77
78 private:
79  int value_;
80
81  unique_fd(const unique_fd&);
82  void operator=(const unique_fd&);
83};
84
85}  // namespace base
86}  // namespace android
87
88#endif  // ANDROID_BASE_UNIQUE_FD_H
89