summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Metal/MRCHelpers.h
blob: 839b24cf60c0132ed4caf11d871e6f9a92cf9ee6 (plain)
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
// Copyright 2022 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

// clang-format off
#ifndef __OBJC__
  #error This header is for use with Objective-C++ only.
#endif
#if __has_feature(objc_arc)
  #error This file is for manual reference counting!  Compile without -fobjc-arc
#endif
// clang-format on

#pragma once

#include <cstddef>
#include <utility>

/// Managed Obj-C pointer
template <typename T>
class MRCOwned
{
  T ptr;
  MRCOwned(T raw_ptr) : ptr(raw_ptr) {}

public:
  MRCOwned() : ptr(nullptr) {}
  MRCOwned(std::nullptr_t) : ptr(nullptr) {}
  MRCOwned(MRCOwned&& other) : ptr(other.ptr) { other.ptr = nullptr; }
  MRCOwned(const MRCOwned& other) : ptr(other.ptr) { [ptr retain]; }
  ~MRCOwned()
  {
    if (ptr)
      [ptr release];
  }
  operator T() const { return ptr; }
  MRCOwned& operator=(const MRCOwned& other)
  {
    [other.ptr retain];
    if (ptr)
      [ptr release];
    ptr = other.ptr;
    return *this;
  }
  MRCOwned& operator=(MRCOwned&& other)
  {
    std::swap(ptr, other.ptr);
    return *this;
  }
  void Reset()
  {
    [ptr release];
    ptr = nullptr;
  }
  T Disown()
  {
    T tmp = ptr;
    ptr = nullptr;
    return tmp;
  }
  T Get() const { return ptr; }
  static MRCOwned Transfer(T ptr) { return MRCOwned(ptr); }
  static MRCOwned Retain(T ptr)
  {
    [ptr retain];
    return MRCOwned(ptr);
  }
};

/// Take ownership of an Obj-C pointer (equivalent to __bridge_transfer)
template <typename T>
static inline MRCOwned<T> MRCTransfer(T ptr)
{
  return MRCOwned<T>::Transfer(ptr);
}

/// Retain an Obj-C pointer (equivalent to __bridge)
template <typename T>
static inline MRCOwned<T> MRCRetain(T ptr)
{
  return MRCOwned<T>::Retain(ptr);
}