-
Notifications
You must be signed in to change notification settings - Fork 5.5k
test: Add a mechanism for creating singletons in tests #5086
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
fc60f23
4cb3e8b
089d912
3e25e3e
c895a8d
c9eac71
5fdf9ea
b60f1d4
4db2e35
ec98812
0210022
74e461c
8766bd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| #include "test/test_common/global.h" | ||
|
|
||
| #include "common/common/assert.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Test { | ||
|
|
||
| Globals& Globals::instance() { | ||
| static Globals* h = new Globals; | ||
| return *h; | ||
| } | ||
|
|
||
| std::string Globals::describeActiveSingletonsHelper() { | ||
| std::string ret; | ||
| Thread::ReleasableLockGuard map_lock(map_mutex_); | ||
| for (auto& p : singleton_map_) { | ||
| std::unique_ptr<Singleton>& singleton = p.second; | ||
| ASSERT(singleton != nullptr); | ||
| if (singleton->ptr_ != nullptr) { | ||
| absl::StrAppend(&ret, "Unexpected active singleton: ", p.first, "\n"); | ||
| } | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| Globals::Singleton& Globals::get(const std::string& type_name, const MakeObjectFn& make_object) { | ||
| Thread::ReleasableLockGuard map_lock(map_mutex_); | ||
| std::unique_ptr<Singleton>& singleton = singleton_map_[type_name]; | ||
|
|
||
| if (singleton == nullptr) { | ||
| // The first time constructing this object, we'll be constructing the | ||
| // Singleton for the first time, populating it with a fresh instance, | ||
| // so no need to take the singleton's mutex. But we do need to hold | ||
| // the map mutex as we are installing the singleton object in the | ||
| // singleton_map. | ||
| singleton = std::make_unique<Singleton>(make_object(), map_mutex_); | ||
| return *singleton; | ||
| } | ||
|
|
||
| // Subsequent accesses will must lock the singleton's mutex to safely populate | ||
| // .second. However, we can relinquish map_mutex_ as we are no longer | ||
| // modifying the map; just the .second of the MutexSingleton pointed to by the | ||
| // map. | ||
|
jmarantz marked this conversation as resolved.
Outdated
|
||
| if (singleton->ptr_ == nullptr) { | ||
| ASSERT(singleton->ref_count_ == 0); | ||
| singleton->ptr_ = make_object(); | ||
| } | ||
| ++singleton->ref_count_; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How come you're not using a shared_ptr/weak_ptr pattern here but doing it by hand?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about this for a bit; couldn't figure out how to make the pieces fit given the heterogenous map and casting.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought of that, but thought it annoying that I'd have to hold a functor for calling the class-specific delete in the singleton. Then I thought I'd give it a shot and it wasn't too bad to just do that, so switching to weak_ptr. |
||
| return *singleton; | ||
| } | ||
|
|
||
| void Globals::Singleton::releaseHelper(const DeleteObjectFn& delete_object) { | ||
| void* obj_to_delete = nullptr; | ||
| { | ||
| Thread::LockGuard singleton_lock(mutex_); | ||
| ASSERT(ptr_ != nullptr); | ||
| if (--ref_count_ == 0) { | ||
| obj_to_delete = ptr_; | ||
| ptr_ = nullptr; | ||
| } | ||
| } | ||
| if (obj_to_delete != nullptr) { | ||
| delete_object(obj_to_delete); | ||
| } | ||
| } | ||
|
|
||
| } // namespace Test | ||
| } // namespace Envoy | ||
Uh oh!
There was an error while loading. Please reload this page.