this repo has no description
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
2#pragma once
3
4#include "handles-decl.h"
5#include "objects.h"
6#include "thread.h"
7
8namespace py {
9
10class WARN_UNUSED HandleScope {
11 public:
12 explicit HandleScope(Thread* thread) : thread_(thread) {}
13
14 Thread* thread() const { return thread_; }
15
16 private:
17 Thread* const thread_;
18
19 DISALLOW_COPY_AND_ASSIGN(HandleScope);
20};
21
22template <typename T>
23class WARN_UNUSED Handle : public T {
24 public:
25 Handle(HandleScope* scope, RawObject obj)
26 : T(obj.rawCast<T>()),
27 thread_(scope->thread()),
28 next_(thread_->handles()->push(pointer())) {
29 DCHECK(isValidType(), "Invalid Handle construction");
30 }
31
32 // Don't allow constructing a Handle directly from another Handle; require
33 // dereferencing the source.
34 template <typename S>
35 Handle(HandleScope*, const Handle<S>&) = delete;
36
37 ~Handle() {
38 DCHECK(thread_->handles()->head() == pointer(), "unexpected this");
39 thread_->handles()->pop(next_);
40 }
41
42 Handle<RawObject>* nextHandle() const { return next_; }
43
44 T operator*() const { return *static_cast<const T*>(this); }
45
46 // Note that Handle<T>::operator= takes a raw pointer, not a handle, so
47 // to assign handles, one writes: `lhandle = *rhandle;`. (This is to avoid
48 // confusion about which HandleScope tracks lhandle after the assignment.)
49 template <typename S>
50 Handle& operator=(S other) {
51 static_assert(std::is_base_of<S, T>::value || std::is_base_of<T, S>::value,
52 "Only up- and down-casts are permitted.");
53 *static_cast<T*>(this) = other.template rawCast<T>();
54 DCHECK(isValidType(), "Invalid Handle assignment");
55 return *this;
56 }
57
58 // Let Handle<T> pretend to be a subtype of Handle<S> when T is a subtype of
59 // S.
60 template <typename S>
61 operator const Handle<S> &() const {
62 static_assert(std::is_base_of<S, T>::value, "Only up-casts are permitted");
63 return *reinterpret_cast<const Handle<S>*>(this);
64 }
65
66 static_assert(std::is_base_of<RawObject, T>::value,
67 "You can only get a handle to a py::RawObject.");
68
69 DISALLOW_IMPLICIT_CONSTRUCTORS(Handle);
70 DISALLOW_HEAP_ALLOCATION();
71
72 private:
73 bool isValidType() const;
74
75 Handle<RawObject>* pointer() {
76 return reinterpret_cast<Handle<RawObject>*>(this);
77 }
78
79 Thread* const thread_;
80 Handle<RawObject>* const next_;
81};
82
83} // namespace py