1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef PLATFORM_IMPL_SCOPED_PIPE_H_ 6*3f982cf4SFabien Sanglard #define PLATFORM_IMPL_SCOPED_PIPE_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <unistd.h> 9*3f982cf4SFabien Sanglard 10*3f982cf4SFabien Sanglard #include <utility> 11*3f982cf4SFabien Sanglard 12*3f982cf4SFabien Sanglard namespace openscreen { 13*3f982cf4SFabien Sanglard 14*3f982cf4SFabien Sanglard struct IntFdTraits { 15*3f982cf4SFabien Sanglard using PipeType = int; 16*3f982cf4SFabien Sanglard static constexpr int kInvalidValue = -1; 17*3f982cf4SFabien Sanglard CloseIntFdTraits18*3f982cf4SFabien Sanglard static void Close(PipeType pipe) { close(pipe); } 19*3f982cf4SFabien Sanglard }; 20*3f982cf4SFabien Sanglard 21*3f982cf4SFabien Sanglard // This class wraps file descriptor and uses RAII to ensure it is closed 22*3f982cf4SFabien Sanglard // properly when control leaves its scope. It is parameterized by a traits type 23*3f982cf4SFabien Sanglard // which defines the value type of the file descriptor, an invalid value, and a 24*3f982cf4SFabien Sanglard // closing function. 25*3f982cf4SFabien Sanglard // 26*3f982cf4SFabien Sanglard // This class is move-only as it represents ownership of the wrapped file 27*3f982cf4SFabien Sanglard // descriptor. It is not thread-safe. 28*3f982cf4SFabien Sanglard template <typename Traits> 29*3f982cf4SFabien Sanglard class ScopedPipe { 30*3f982cf4SFabien Sanglard public: 31*3f982cf4SFabien Sanglard using PipeType = typename Traits::PipeType; 32*3f982cf4SFabien Sanglard ScopedPipe()33*3f982cf4SFabien Sanglard ScopedPipe() : pipe_(Traits::kInvalidValue) {} ScopedPipe(PipeType pipe)34*3f982cf4SFabien Sanglard explicit ScopedPipe(PipeType pipe) : pipe_(pipe) {} 35*3f982cf4SFabien Sanglard ScopedPipe(const ScopedPipe&) = delete; ScopedPipe(ScopedPipe && other)36*3f982cf4SFabien Sanglard ScopedPipe(ScopedPipe&& other) : pipe_(other.release()) {} ~ScopedPipe()37*3f982cf4SFabien Sanglard ~ScopedPipe() { 38*3f982cf4SFabien Sanglard if (pipe_ != Traits::kInvalidValue) 39*3f982cf4SFabien Sanglard Traits::Close(release()); 40*3f982cf4SFabien Sanglard } 41*3f982cf4SFabien Sanglard 42*3f982cf4SFabien Sanglard ScopedPipe& operator=(ScopedPipe&& other) { 43*3f982cf4SFabien Sanglard if (pipe_ != Traits::kInvalidValue) 44*3f982cf4SFabien Sanglard Traits::Close(release()); 45*3f982cf4SFabien Sanglard pipe_ = other.release(); 46*3f982cf4SFabien Sanglard return *this; 47*3f982cf4SFabien Sanglard } 48*3f982cf4SFabien Sanglard get()49*3f982cf4SFabien Sanglard PipeType get() const { return pipe_; } release()50*3f982cf4SFabien Sanglard PipeType release() { 51*3f982cf4SFabien Sanglard PipeType pipe = pipe_; 52*3f982cf4SFabien Sanglard pipe_ = Traits::kInvalidValue; 53*3f982cf4SFabien Sanglard return pipe; 54*3f982cf4SFabien Sanglard } 55*3f982cf4SFabien Sanglard 56*3f982cf4SFabien Sanglard bool operator==(const ScopedPipe& other) const { 57*3f982cf4SFabien Sanglard return pipe_ == other.pipe_; 58*3f982cf4SFabien Sanglard } 59*3f982cf4SFabien Sanglard bool operator!=(const ScopedPipe& other) const { return !(*this == other); } 60*3f982cf4SFabien Sanglard 61*3f982cf4SFabien Sanglard explicit operator bool() const { return pipe_ != Traits::kInvalidValue; } 62*3f982cf4SFabien Sanglard 63*3f982cf4SFabien Sanglard private: 64*3f982cf4SFabien Sanglard PipeType pipe_; 65*3f982cf4SFabien Sanglard }; 66*3f982cf4SFabien Sanglard 67*3f982cf4SFabien Sanglard using ScopedFd = ScopedPipe<IntFdTraits>; 68*3f982cf4SFabien Sanglard 69*3f982cf4SFabien Sanglard } // namespace openscreen 70*3f982cf4SFabien Sanglard 71*3f982cf4SFabien Sanglard #endif // PLATFORM_IMPL_SCOPED_PIPE_H_ 72