1// vim:set ft=cpp: -*- Mode: C++ -*-
2/**
3 * \file
4 *
5 */
6/*
7 * (c) 2017 Alexander Warg <alexander.warg@kernkonzept.com>
8 *
9 * This file is part of TUD:OS and distributed under the terms of the
10 * GNU General Public License 2.
11 * Please see the COPYING-GPL-2 file for details.
12 *
13 * As a special exception, you may use this file as part of a free software
14 * library without restriction.  Specifically, if other files instantiate
15 * templates or use macros or inline functions from this file, or you compile
16 * this file and link it with other files to produce an executable, this
17 * file does not by itself cause the resulting executable to be covered by
18 * the GNU General Public License.  This exception does not however
19 * invalidate any other reasons why the executable file might be covered by
20 * the GNU General Public License.
21 */
22
23#pragma once
24
25#include <l4/sys/capability>
26
27namespace L4 { namespace Detail {
28
29template< typename T, typename IMPL >
30class Smart_cap_base : public Cap_base, protected IMPL
31{
32protected:
33  template<typename X>
34  static IMPL &impl(Smart_cap_base<X, IMPL> &o) { return o; }
35
36  template<typename X>
37  static IMPL const &impl(Smart_cap_base<X, IMPL> const &o) { return o; }
38
39public:
40  template<typename X, typename I>
41  friend class ::L4::Detail::Smart_cap_base;
42
43  Smart_cap_base(Smart_cap_base const &) = delete;
44  Smart_cap_base &operator = (Smart_cap_base const &) = delete;
45
46  Smart_cap_base() noexcept : Cap_base(Invalid) {}
47
48  explicit Smart_cap_base(Cap_base::Cap_type t) noexcept
49  : Cap_base(t)
50  {}
51
52  template<typename O>
53  explicit constexpr Smart_cap_base(Cap<O> c) noexcept
54  : Cap_base(c.cap())
55  {}
56
57  template<typename O>
58  explicit constexpr Smart_cap_base(Cap<O> c, IMPL const &impl) noexcept
59  : Cap_base(c.cap()), IMPL(impl)
60  {}
61
62  Cap<T> release() noexcept
63  {
64    l4_cap_idx_t c = this->cap();
65    IMPL::invalidate(*this);
66    return Cap<T>(c);
67  }
68
69  void reset()
70  { IMPL::free(*this); }
71
72  Cap<T> operator -> () const noexcept { return Cap<T>(this->cap()); }
73  Cap<T> get() const noexcept { return Cap<T>(this->cap()); }
74  ~Smart_cap_base() noexcept { IMPL::free(*this); }
75};
76
77
78template< typename T, typename IMPL >
79class Unique_cap_impl final :  public Smart_cap_base<T, IMPL>
80{
81private:
82  typedef Smart_cap_base<T, IMPL> Base;
83
84public:
85  using Base::Base;
86  Unique_cap_impl() noexcept = default;
87
88  Unique_cap_impl(Unique_cap_impl &&o) noexcept
89  : Base(o.release(), Base::impl(o))
90  {}
91
92  template<typename O>
93  Unique_cap_impl(Unique_cap_impl<O, IMPL> &&o) noexcept
94  : Base(o.release(), Base::impl(o))
95  { T* __t = ((O*)100); (void)__t; }
96
97  Unique_cap_impl &operator = (Unique_cap_impl &&o) noexcept
98  {
99    if (&o == this)
100      return *this;
101
102    IMPL::free(*this);
103    this->_c = o.release().cap();
104    this->IMPL::operator = (Base::impl(o));
105    return *this;
106  }
107
108  template<typename O>
109  Unique_cap_impl &operator = (Unique_cap_impl<O, IMPL> &&o) noexcept
110  {
111    T* __t = ((O*)100); (void)__t;
112
113    IMPL::free(*this);
114    this->_c = o.release().cap();
115    this->IMPL::operator = (Base::impl(o));
116    return *this;
117  }
118};
119
120template<typename T, typename IMPL>
121class Shared_cap_impl final : public Smart_cap_base<T, IMPL>
122{
123private:
124  typedef Smart_cap_base<T, IMPL> Base;
125
126public:
127  using Base::Base;
128  Shared_cap_impl() noexcept = default;
129
130  Shared_cap_impl(Shared_cap_impl &&o) noexcept
131  : Base(o.release())
132  {}
133
134  template<typename O>
135  Shared_cap_impl(Shared_cap_impl<O, IMPL> &&o) noexcept
136  : Base(o.release())
137  { T* __t = ((O*)100); (void)__t; }
138
139  Shared_cap_impl &operator = (Shared_cap_impl &&o) noexcept
140  {
141    if (&o == this)
142      return *this;
143
144    IMPL::free(*this);
145    this->_c = o.release().cap();
146    this->IMPL::operator = (Base::impl(o));
147    return *this;
148  }
149
150  template<typename O>
151  Shared_cap_impl &operator = (Shared_cap_impl<O, IMPL> &&o) noexcept
152  {
153    T* __t = ((O*)100); (void)__t;
154
155    IMPL::free(*this);
156    this->_c = o.release().cap();
157    this->IMPL::operator = (Base::impl(o));
158    return *this;
159  }
160
161  Shared_cap_impl(Shared_cap_impl const &o) noexcept
162  : Base(L4::Cap<T>(IMPL::copy(o).cap()))
163  {}
164
165  template<typename O>
166  Shared_cap_impl(Shared_cap_impl<O, IMPL> const &o) noexcept
167  : Base(IMPL::copy(o))
168  { T* __t = ((O*)100); (void)__t; }
169
170  Shared_cap_impl &operator = (Shared_cap_impl const &o) noexcept
171  {
172    if (&o == this)
173      return *this;
174
175    IMPL::free(*this);
176    this->IMPL::operator = (static_cast<IMPL const &>(o));
177    this->_c = this->IMPL::copy(o).cap();
178    return *this;
179  }
180
181  template<typename O>
182  Shared_cap_impl &operator = (Shared_cap_impl<O, IMPL> const &o) noexcept
183  {
184    T* __t = ((O*)100); (void)__t;
185    IMPL::free(*this);
186    this->IMPL::operator = (static_cast<IMPL const &>(o));
187    this->_c = this->IMPL::copy(o).cap();
188    return *this;
189  }
190};
191
192}} // L4::Detail
193