-
Notifications
You must be signed in to change notification settings - Fork 585
Freeze registries at startup, when everything has been registered #10388
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
Open
Al2Klimov
wants to merge
8
commits into
master
Choose a base branch
from
Registry-Freeze
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3fd3d52
Remove unused Registry#OnUnregistered
Al2Klimov 3f2b5f1
Remove unused Registry#OnRegistered
Al2Klimov 18e557e
Inline Registry#RegisterInternal() used only once
Al2Klimov 0264d7b
Make Registry#ItemMap a hash table to speed up lookups
Al2Klimov a13b69b
Registry#Get*(): use shared locking to allow concurrent access
Al2Klimov 031d7f9
Introduce Registry#Freeze()
Al2Klimov 24f50d5
Introduce Registry::GetInstance() to deduplicate such methods
Al2Klimov e4bfbf2
Actually use Registry#Freeze() at startup, when everything has been r…
Al2Klimov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,13 @@ | |
#define REGISTRY_H | ||
|
||
#include "base/i2-base.hpp" | ||
#include "base/atomic.hpp" | ||
#include "base/exception.hpp" | ||
#include "base/string.hpp" | ||
#include <boost/signals2.hpp> | ||
#include <map> | ||
#include "base/singleton.hpp" | ||
#include <shared_mutex> | ||
#include <stdexcept> | ||
#include <unordered_map> | ||
#include <mutex> | ||
|
||
namespace icinga | ||
|
@@ -21,18 +25,27 @@ template<typename U, typename T> | |
class Registry | ||
{ | ||
public: | ||
typedef std::map<String, T> ItemMap; | ||
typedef std::unordered_map<String, T> ItemMap; | ||
|
||
static Registry* GetInstance() | ||
{ | ||
return Singleton<Registry>::GetInstance(); | ||
} | ||
|
||
void Register(const String& name, const T& item) | ||
{ | ||
std::unique_lock<std::mutex> lock(m_Mutex); | ||
std::unique_lock lock (m_Mutex); | ||
|
||
if (m_Frozen) { | ||
BOOST_THROW_EXCEPTION(std::logic_error("Registry is read-only and must not be modified.")); | ||
} | ||
|
||
RegisterInternal(name, item, lock); | ||
m_Items[name] = item; | ||
} | ||
|
||
T GetItem(const String& name) const | ||
{ | ||
std::unique_lock<std::mutex> lock(m_Mutex); | ||
auto lock (ReadLockUnlessFrozen()); | ||
|
||
auto it = m_Items.find(name); | ||
|
||
|
@@ -44,33 +57,36 @@ class Registry | |
|
||
ItemMap GetItems() const | ||
{ | ||
std::unique_lock<std::mutex> lock(m_Mutex); | ||
auto lock (ReadLockUnlessFrozen()); | ||
|
||
return m_Items; /* Makes a copy of the map. */ | ||
} | ||
|
||
boost::signals2::signal<void (const String&, const T&)> OnRegistered; | ||
boost::signals2::signal<void (const String&)> OnUnregistered; | ||
/** | ||
* Freeze the registry, preventing further updates. | ||
* | ||
* This only prevents inserting, replacing or deleting values from the registry. | ||
* This operation has no effect on objects referenced by the values, these remain mutable if they were before. | ||
*/ | ||
void Freeze() | ||
{ | ||
std::unique_lock lock (m_Mutex); | ||
|
||
m_Frozen.store(true); | ||
} | ||
|
||
private: | ||
mutable std::mutex m_Mutex; | ||
mutable std::shared_mutex m_Mutex; | ||
Atomic<bool> m_Frozen {false}; | ||
typename Registry<U, T>::ItemMap m_Items; | ||
|
||
void RegisterInternal(const String& name, const T& item, std::unique_lock<std::mutex>& lock) | ||
std::shared_lock<std::shared_mutex> ReadLockUnlessFrozen() const | ||
{ | ||
bool old_item = false; | ||
|
||
if (m_Items.erase(name) > 0) | ||
old_item = true; | ||
|
||
m_Items[name] = item; | ||
|
||
lock.unlock(); | ||
|
||
if (old_item) | ||
OnUnregistered(name); | ||
if (m_Frozen.load(std::memory_order_relaxed)) { | ||
return {}; | ||
} | ||
|
||
OnRegistered(name, item); | ||
return std::shared_lock(m_Mutex); | ||
} | ||
Comment on lines
+83
to
90
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. |
||
}; | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also perform this check before even locking the mutex. I don't understand this, if you need the mutex for
m_Frozen
as well, why make it atomic?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't answer the questions! And no, you didn’t do exactly the same.
icinga2/lib/base/namespace.cpp
Lines 52 to 56 in 0613381
icinga2/lib/base/namespace.cpp
Lines 94 to 98 in 0613381
icinga2/lib/base/namespace.cpp
Lines 120 to 122 in 0613381
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it IS the same: Register/Freeze
It's critical to synchronize them! Imagine:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not!
I don't get it! It's for a reason atomic and if you can't synchronise those without a mutex why make it atomic then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could argue for centuries...
I can't synchronise write ops without a mutex. m_Frozen is atomic to speed up read ops.