Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 1 | // Copyright 2019 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #ifndef VK_DEBUG_CONTEXT_HPP_ |
| 16 | #define VK_DEBUG_CONTEXT_HPP_ |
| 17 | |
| 18 | #include "ID.hpp" |
| 19 | |
| 20 | #include <memory> |
| 21 | #include <string> |
Ben Clayton | 4fbe46d | 2020-09-25 18:29:18 +0100 | [diff] [blame] | 22 | #include <unordered_set> |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 23 | #include <vector> |
| 24 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 25 | namespace vk { |
| 26 | namespace dbg { |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 27 | |
| 28 | // Forward declarations. |
| 29 | class Thread; |
| 30 | class File; |
| 31 | class Frame; |
| 32 | class Scope; |
Ben Clayton | ce1584d | 2020-09-25 18:13:42 +0100 | [diff] [blame] | 33 | class Variables; |
Ben Clayton | aa58f0c | 2020-09-25 17:45:13 +0100 | [diff] [blame] | 34 | class ClientEventListener; |
| 35 | class ServerEventListener; |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 36 | |
| 37 | // Context holds the full state of the debugger, including all current files, |
| 38 | // threads, frames and variables. It also holds a list of EventListeners that |
| 39 | // can be broadcast to using the Context::broadcast() interface. |
| 40 | // Context requires locking before accessing any state. The lock is |
| 41 | // non-reentrant and careful use is required to prevent accidentical |
| 42 | // double-locking by the same thread. |
| 43 | class Context |
| 44 | { |
| 45 | class Impl; |
| 46 | |
| 47 | public: |
| 48 | // Lock is the interface to the Context's state. |
| 49 | // The lock is automatically released when the Lock is destructed. |
| 50 | class Lock |
| 51 | { |
| 52 | public: |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 53 | Lock(Impl *); |
| 54 | Lock(Lock &&); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 55 | ~Lock(); |
| 56 | |
| 57 | // move-assignment operator. |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 58 | Lock &operator=(Lock &&); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 59 | |
| 60 | // unlock() explicitly unlocks before the Lock destructor is called. |
| 61 | // It is illegal to call any other methods after calling unlock(). |
| 62 | void unlock(); |
| 63 | |
| 64 | // currentThread() creates (or returns an existing) a Thread that |
| 65 | // represents the currently executing thread. |
| 66 | std::shared_ptr<Thread> currentThread(); |
| 67 | |
| 68 | // get() returns the thread with the given ID, or null if the thread |
| 69 | // does not exist or no longer has any external shared_ptr references. |
| 70 | std::shared_ptr<Thread> get(ID<Thread>); |
| 71 | |
| 72 | // threads() returns the full list of threads that still have an |
| 73 | // external shared_ptr reference. |
| 74 | std::vector<std::shared_ptr<Thread>> threads(); |
| 75 | |
| 76 | // createVirtualFile() returns a new file that is not backed by the |
| 77 | // filesystem. |
| 78 | // name is the unique name of the file. |
| 79 | // source is the content of the file. |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 80 | std::shared_ptr<File> createVirtualFile(const std::string &name, |
| 81 | const std::string &source); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 82 | |
| 83 | // createPhysicalFile() returns a new file that is backed by the file |
| 84 | // at path. |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 85 | std::shared_ptr<File> createPhysicalFile(const std::string &path); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 86 | |
| 87 | // get() returns the file with the given ID, or null if the file |
| 88 | // does not exist or no longer has any external shared_ptr references. |
| 89 | std::shared_ptr<File> get(ID<File>); |
| 90 | |
Ben Clayton | 1075bae | 2020-09-25 18:47:22 +0100 | [diff] [blame] | 91 | // findFile() returns the file with the given path, or nullptr if not |
| 92 | // found. |
| 93 | std::shared_ptr<File> findFile(const std::string &path); |
| 94 | |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 95 | // files() returns the full list of files. |
| 96 | std::vector<std::shared_ptr<File>> files(); |
| 97 | |
Ben Clayton | 3775f6d | 2020-01-08 11:51:34 +0000 | [diff] [blame] | 98 | // createFrame() returns a new frame for the given file and function |
| 99 | // name. |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 100 | std::shared_ptr<Frame> createFrame( |
Ben Clayton | 3775f6d | 2020-01-08 11:51:34 +0000 | [diff] [blame] | 101 | const std::shared_ptr<File> &file, std::string function); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 102 | |
| 103 | // get() returns the frame with the given ID, or null if the frame |
| 104 | // does not exist or no longer has any external shared_ptr references. |
| 105 | std::shared_ptr<Frame> get(ID<Frame>); |
| 106 | |
| 107 | // createScope() returns a new scope for the given file. |
| 108 | std::shared_ptr<Scope> createScope( |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 109 | const std::shared_ptr<File> &file); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 110 | |
| 111 | // get() returns the scope with the given ID, or null if the scope |
| 112 | // does not exist. |
| 113 | std::shared_ptr<Scope> get(ID<Scope>); |
| 114 | |
Ben Clayton | ce1584d | 2020-09-25 18:13:42 +0100 | [diff] [blame] | 115 | // track() registers the variables with the context so it can be |
| 116 | // retrieved by get(). Note that the context does not hold a strong |
| 117 | // reference to the variables, and get() will return nullptr if all |
| 118 | // strong external references are dropped. |
| 119 | void track(const std::shared_ptr<Variables> &); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 120 | |
Ben Clayton | ce1584d | 2020-09-25 18:13:42 +0100 | [diff] [blame] | 121 | // get() returns the variables with the given ID, or null if the |
| 122 | // variables does not exist or no longer has any external shared_ptr |
| 123 | // references. |
| 124 | std::shared_ptr<Variables> get(ID<Variables>); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 125 | |
Ben Clayton | 4fbe46d | 2020-09-25 18:29:18 +0100 | [diff] [blame] | 126 | // clearFunctionBreakpoints() removes all function breakpoints. |
| 127 | void clearFunctionBreakpoints(); |
| 128 | |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 129 | // addFunctionBreakpoint() adds a breakpoint to the start of the |
| 130 | // function with the given name. |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 131 | void addFunctionBreakpoint(const std::string &name); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 132 | |
| 133 | // addPendingBreakpoints() adds a number of breakpoints to the file with |
| 134 | // the given name which has not yet been created with a call to |
| 135 | // createVirtualFile() or createPhysicalFile(). |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 136 | void addPendingBreakpoints(const std::string &name, const std::vector<int> &lines); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 137 | |
| 138 | // isFunctionBreakpoint() returns true if the function with the given |
| 139 | // name has a function breakpoint set. |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 140 | bool isFunctionBreakpoint(const std::string &name); |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 141 | |
Ben Clayton | 4fbe46d | 2020-09-25 18:29:18 +0100 | [diff] [blame] | 142 | // getFunctionBreakpoints() returns all the set function breakpoints. |
| 143 | std::unordered_set<std::string> getFunctionBreakpoints(); |
| 144 | |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 145 | private: |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 146 | Lock(const Lock &) = delete; |
| 147 | Lock &operator=(const Lock &) = delete; |
| 148 | Impl *ctx; |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 149 | }; |
| 150 | |
| 151 | // create() creates and returns a new Context. |
| 152 | static std::shared_ptr<Context> create(); |
| 153 | |
| 154 | virtual ~Context() = default; |
| 155 | |
| 156 | // lock() returns a Lock which exclusively locks the context for state |
| 157 | // access. |
| 158 | virtual Lock lock() = 0; |
| 159 | |
Ben Clayton | aa58f0c | 2020-09-25 17:45:13 +0100 | [diff] [blame] | 160 | // addListener() registers an ClientEventListener for event notifications. |
| 161 | virtual void addListener(ClientEventListener *) = 0; |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 162 | |
Ben Clayton | aa58f0c | 2020-09-25 17:45:13 +0100 | [diff] [blame] | 163 | // removeListener() unregisters an ClientEventListener that was previously |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 164 | // registered by a call to addListener(). |
Ben Clayton | aa58f0c | 2020-09-25 17:45:13 +0100 | [diff] [blame] | 165 | virtual void removeListener(ClientEventListener *) = 0; |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 166 | |
Ben Clayton | aa58f0c | 2020-09-25 17:45:13 +0100 | [diff] [blame] | 167 | // clientEventBroadcast() returns an ClientEventListener that will broadcast |
| 168 | // all method calls on to all registered ServerEventListeners. |
| 169 | virtual ClientEventListener *clientEventBroadcast() = 0; |
| 170 | |
| 171 | // addListener() registers an ServerEventListener for event notifications. |
| 172 | virtual void addListener(ServerEventListener *) = 0; |
| 173 | |
| 174 | // removeListener() unregisters an ServerEventListener that was previously |
| 175 | // registered by a call to addListener(). |
| 176 | virtual void removeListener(ServerEventListener *) = 0; |
| 177 | |
| 178 | // serverEventBroadcast() returns an ServerEventListener that will broadcast |
| 179 | // all method calls on to all registered ServerEventListeners. |
| 180 | virtual ServerEventListener *serverEventBroadcast() = 0; |
Ben Clayton | a5859c1 | 2019-12-02 20:12:03 +0000 | [diff] [blame] | 181 | }; |
| 182 | |
| 183 | } // namespace dbg |
| 184 | } // namespace vk |
| 185 | |
| 186 | #endif // VK_DEBUG_CONTEXT_HPP_ |