1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20/*!
21 * \file tvm/support/with.h
22 * \brief RAII wrapper function to enter and exit a context object
23 * similar to python's with syntax.
24 */
25#ifndef TVM_SUPPORT_WITH_H_
26#define TVM_SUPPORT_WITH_H_
27
28#include <dmlc/common.h>
29
30#include <functional>
31#include <utility>
32
33namespace tvm {
34
35/*!
36 * \brief RAII wrapper function to enter and exit a context object
37 * similar to python's with syntax.
38 *
39 * \code
40 * // context class
41 * class MyContext {
42 * private:
43 * friend class With<MyContext>;
44 MyContext(arguments);
45 * void EnterWithScope();
46 * void ExitWithScope();
47 * };
48 *
49 * {
50 * With<MyContext> scope(arguments);
51 * // effect take place.
52 * }
53 * \endcode
54 *
55 * \tparam ContextType Type of the context object.
56 */
57template <typename ContextType>
58class With {
59 public:
60 /*!
61 * \brief constructor.
62 * Enter the scope of the context.
63 */
64 template <typename... Args>
65 explicit With(Args&&... args) : ctx_(std::forward<Args>(args)...) {
66 ctx_.EnterWithScope();
67 }
68 /*! \brief destructor, leaves the scope of the context. */
69 ~With() DMLC_THROW_EXCEPTION { ctx_.ExitWithScope(); }
70
71 // Disable copy and move construction. `With` is intended only for
72 // use in nested contexts that are exited in the reverse order of
73 // entry. Allowing context to be copied or moved would break this
74 // expectation.
75 With(const With& other) = delete;
76 With& operator=(const With& other) = delete;
77 With(With&& other) = delete;
78 With& operator=(With&& other) = delete;
79
80 ContextType* get() { return &ctx_; }
81 const ContextType* get() const { return &ctx_; }
82
83 ContextType* operator->() { return get(); }
84 const ContextType* operator->() const { return get(); }
85 ContextType& operator*() { return *get(); }
86 const ContextType* operator*() const { return *get(); }
87
88 ContextType operator()() { return ctx_; }
89
90 private:
91 /*! \brief internal context type. */
92 ContextType ctx_;
93};
94
95} // namespace tvm
96#endif // TVM_SUPPORT_WITH_H_
97