| 269 | } |
| 270 | |
| 271 | shared_ptr<MemoryTracker> MemoryTrackerManager::create_tracker( |
| 272 | uint64_t memory_budget, std::function<void()> on_budget_exceeded) { |
| 273 | /* |
| 274 | * The MemoryTracker class has a protected constructor to hopefully help |
| 275 | * self-document that instances should almost never be created directly |
| 276 | * except in test code. There exists a |
| 277 | * `tiledb::test::create_test_memory_tracker()` API that can be used in |
| 278 | * tests to create untracked instances of MemoryTracker. |
| 279 | * |
| 280 | * This just uses the standard private derived class to enable the use of |
| 281 | * `make_shared` to create instances in specific bits of code. |
| 282 | */ |
| 283 | class MemoryTrackerCreator : public MemoryTracker { |
| 284 | public: |
| 285 | /** |
| 286 | * Pass through to the protected MemoryTracker constructor for |
| 287 | * make_shared. |
| 288 | */ |
| 289 | MemoryTrackerCreator( |
| 290 | uint64_t memory_budget, std::function<void()> on_budget_exceeded) |
| 291 | : MemoryTracker(memory_budget, on_budget_exceeded) { |
| 292 | } |
| 293 | }; |
| 294 | |
| 295 | std::lock_guard<std::mutex> lg(mutex_); |
| 296 | |
| 297 | // Delete any expired weak_ptr instances |
| 298 | size_t idx = 0; |
| 299 | while (idx < trackers_.size()) { |
| 300 | if (trackers_[idx].expired()) { |
| 301 | trackers_.erase(trackers_.begin() + idx); |
| 302 | } else { |
| 303 | idx++; |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | // Create a new tracker |
| 308 | auto ret = make_shared<MemoryTrackerCreator>( |
| 309 | HERE(), memory_budget, on_budget_exceeded); |
| 310 | trackers_.emplace(trackers_.begin(), ret); |
| 311 | |
| 312 | return ret; |
| 313 | } |
| 314 | |
| 315 | std::string MemoryTrackerManager::to_json() { |
| 316 | std::lock_guard<std::mutex> lg(mutex_); |