{"id":6513,"date":"2023-02-12T16:06:53","date_gmt":"2023-02-12T16:06:53","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/the-null-object-pattern\/"},"modified":"2023-08-20T14:39:16","modified_gmt":"2023-08-20T14:39:16","slug":"the-null-object-pattern","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/the-null-object-pattern\/","title":{"rendered":"The Null Object Pattern"},"content":{"rendered":"<p>A Null Object encapsulates a do nothing behavior inside an object. It is often pretty comfortable to use a neutral object.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6503\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/ClassIdioms.png\" alt=\"ClassIdioms\" width=\"650\" height=\"335\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/ClassIdioms.png 1224w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/ClassIdioms-300x154.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/ClassIdioms-1024x527.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/ClassIdioms-768x395.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>A Null Object<\/p>\n<ul>\n<li>encapsulates the do nothing behavior inside an object.<\/li>\n<li>supports the workflow without conditional logic.<\/li>\n<li>hides the special use cases from the client.<\/li>\n<\/ul>\n<p>Honestly, there is not much to write about the Null Object. Let me, therefore, give you an example, using a Null Object.<\/p>\n<h2>Strategized Locking<\/h2>\n<p>Assume you write code such as a library, which should be used in various domains, including concurrent ones. To be on the safe side, you protect the critical sections with a lock. If your library now runs in a single-threaded environment, you have a performance issue because you implemented an expensive synchronization mechanism that is unnecessary. Now, strategized locking comes to your rescue.<\/p>\n<p>Strategized locking is the idea of the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Strategy_pattern\">Strategy Pattern<\/a> applied to locking. This means putting your locking strategy into an object and making it into a pluggable component of your system.<\/p>\n<p>There are two typical ways to implement strategized locking: run-time polymorphism (object orientation) or compile-time polymorphism (templates).<br \/>Both ways improve the customization and extension of the locking strategy, ease the maintenance of the system, and support the reuse of components. Also, implementing the strategized locking at run-time or compile-time differ in various aspects.<\/p>\n<h3>Advantages<\/h3>\n<h4>Run-Time Polymorphism<\/h4>\n<ul>\n<li>Allows it to configure the locking strategy during run time<\/li>\n<li>Is easier to understand for developers who have an object-oriented background<\/li>\n<\/ul>\n<h4>Compile-Time Polymorphism<\/h4>\n<ul>\n<li>Has no abstraction penalty<\/li>\n<li>Has a flat hierarchy.<\/li>\n<\/ul>\n<h3>Disadvantages<\/h3>\n<h4>Run-Time Polymorphism<\/h4>\n<ul>\n<li>Needs an additional pointer or reference indirection<\/li>\n<li>It may have a deep derivation hierarchy<\/li>\n<\/ul>\n<h4>Compile-Time Polymorphism<\/h4>\n<ul>\n<li>It may generate very wordy error messages.<\/li>\n<\/ul>\n<h3>Implementation based on Run-Time Polymorphism<\/h3>\n<p>&nbsp;The program <code>strategizedLockingRuntime.cpp<\/code> presents three different mutexes.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ strategizedLockingRuntime.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;shared_mutex&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Lock<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">StrategizedLocking<\/span> {\r\n    Lock<span style=\"color: #555555;\">&amp;<\/span> lock;                                  <em><span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    StrategizedLocking(Lock<span style=\"color: #555555;\">&amp;<\/span> l)<span style=\"color: #555555;\">:<\/span> lock(l){\r\n        lock.lock();                             <em><span style=\"color: #0099ff;\">\/\/ (2)<\/span><\/em>\r\n    }\r\n    <span style=\"color: #555555;\">~<\/span>StrategizedLocking(){\r\n        lock.unlock();                           <em><span style=\"color: #0099ff;\">\/\/ (3)<\/span><\/em>\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> NullObjectMutex{                          \r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock(){}\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock(){}\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">NoLock<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Lock {                     <em><span style=\"color: #0099ff;\">\/\/ (4)<\/span><\/em>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        nullObjectMutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n         nullObjectMutex.unlock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> NullObjectMutex nullObjectMutex;     <em><span style=\"color: #0099ff;\">\/\/ (9)<\/span><\/em>\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ExclusiveLock<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Lock {              <em><span style=\"color: #0099ff;\">\/\/ (5)<\/span><\/em>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.unlock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>mutex mutex;                    <em><span style=\"color: #0099ff;\">\/\/ (10)<\/span><\/em>\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">SharedLock<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Lock {                 <em><span style=\"color: #0099ff;\">\/\/ (6)<\/span><\/em>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::lock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.lock_shared();                <em><span style=\"color: #0099ff;\">\/\/ (7)<\/span><\/em>\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::unlock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.unlock_shared();              <em><span style=\"color: #0099ff;\">\/\/ (8)<\/span><\/em>\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>shared_mutex sharedMutex;        <em><span style=\"color: #0099ff;\">\/\/ (11)<\/span><\/em>\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    \r\n    NoLock noLock;\r\n    StrategizedLocking stratLock1{noLock};\r\n    \r\n    {\r\n        ExclusiveLock exLock;\r\n        StrategizedLocking stratLock2{exLock};\r\n        {\r\n            SharedLock sharLock;\r\n            StrategizedLocking startLock3{sharLock};\r\n        }\r\n    }\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The class <code>StrategizedLocking<\/code> has a lock (line 1). <code>StrategizedLocking<\/code> models <a href=\"https:\/\/www.dre.vanderbilt.edu\/~schmidt\/PDF\/ScopedLocking.pdf\">scoped locking<\/a> and, therefore, locks the mutex in the constructor (line 2) and unlocks it in the destructor (line 3). <code>Lock<\/code> is an abstract class and defines all derived classes\u2019 interfaces. These are the classes <code>NoLock<\/code> (line 4), <code>ExclusiveLock<\/code> (line 5), and <code>SharedLock <\/code>(line 6). <code>SharedLock<\/code> invokes <code>lock_shared<\/code> (line 7) and <code>unlock_shared<\/code> (line 8) on its <code>std::shared_mutex<\/code>. Each of these locks holds one of the mutexes <code>NullObjectMutex<\/code> (line 9),<code> std::mutex<\/code> (line 10), or <code>std::shared_mutex<\/code> (line 11). <code>NullObjectMutex<\/code> is a noop placeholder. The mutexes are declared as <code>mutable<\/code>. Therefore, they are usable in constant member functions such as <code>lock<\/code> and <code>unlock<\/code>.<\/p>\n<h3>Implementation based on Compile-Time Polymorphism<\/h3>\n<p>&nbsp;The template-based implementation is quite similar to the object-oriented-based implementation.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ strategizedLockingCompileTime.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;shared_mutex&gt;<\/span>\r\n\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Lock<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">StrategizedLocking<\/span> {\r\n    Lock<span style=\"color: #555555;\">&amp;<\/span> lock;\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    StrategizedLocking(Lock<span style=\"color: #555555;\">&amp;<\/span> l)<span style=\"color: #555555;\">:<\/span> lock(l){\r\n        lock.lock();\r\n    }\r\n    <span style=\"color: #555555;\">~<\/span>StrategizedLocking(){\r\n        lock.unlock();\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> NullObjectMutex {\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock(){}\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock(){}\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">NoLock<\/span>{                                         <em><span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        nullObjectMutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n         nullObjectMutex.lock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> NullObjectMutex nullObjectMutex;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ExclusiveLock<\/span> {                                  <em><span style=\"color: #0099ff;\">\/\/ (2)<\/span><\/em>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.unlock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>mutex mutex;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">SharedLock<\/span> {                                     <em><span style=\"color: #0099ff;\">\/\/ (3)<\/span><\/em>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::lock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.lock_shared();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::unlock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.unlock_shared();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>shared_mutex sharedMutex;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    \r\n    NoLock noLock;\r\n    StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>NoLock<span style=\"color: #555555;\">&gt;<\/span> stratLock1{noLock};\r\n    \r\n    {\r\n        ExclusiveLock exLock;\r\n        StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>ExclusiveLock<span style=\"color: #555555;\">&gt;<\/span> stratLock2{exLock};\r\n        {\r\n            SharedLock sharLock;\r\n            StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>SharedLock<span style=\"color: #555555;\">&gt;<\/span> startLock3{sharLock};\r\n        }\r\n    }\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The programs <code>strategizedLockingRuntime.cpp<\/code> and<code> strategizedLockingCompileTime.cpp<\/code> produce the same output:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6512\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/02\/strategizedLocking.png\" alt=\"strategizedLocking\" width=\"510\" height=\"457\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/02\/strategizedLocking.png 510w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/02\/strategizedLocking-300x269.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/p>\n<p>The locks <code>NoLock<\/code> (line 1), <code>ExclusiveLock<\/code> (line 2), and <code>SharedLock<\/code> (line 3) have no abstract base class. The consequence is that <code>StrategizedLocking<\/code> can be instantiated with an object that does not support the right interface. This instantiation would end in a compile-time error. This loophole is closed with C++20.<\/p>\n<h4>The Concept BasicLockable<\/h4>\n<p>Instead of<code> template &lt;typename Lock&gt; class StrategizedLocking<\/code> you can use the<br \/>concept <code>BasicLockable<\/code>:<code> template &lt;BasicLockable Lock&gt; class StrategizedLocking.<\/code> This means that all used locks have to support the concept <code>BasicLockable<\/code>. A concept is a named requirement, and many concepts are already defined in the C++20 concepts library. The concept <code>BasicLockable<\/code> is only used in the text of the C++20 standard. Consequently, I define and use the concept <code>BasicLockable<\/code> in the following improved implementation of the strategized locking at compile time.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ strategizedLockingCompileTimeWithConcepts.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;shared_mutex&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T<span style=\"color: #555555;\">&gt;                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span><\/span>\r\nconcept BasicLockable <span style=\"color: #555555;\">=<\/span> requires(T lo) {\r\n    lo.lock();\r\n    lo.unlock();\r\n};\r\n    \r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>BasicLockable Lock<span style=\"color: #555555;\">&gt;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">StrategizedLocking<\/span> {\r\n    Lock<span style=\"color: #555555;\">&amp;<\/span> lock;\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    StrategizedLocking(Lock<span style=\"color: #555555;\">&amp;<\/span> l)<span style=\"color: #555555;\">:<\/span> lock(l){\r\n        lock.lock();\r\n    }\r\n    <span style=\"color: #555555;\">~<\/span>StrategizedLocking(){\r\n        lock.unlock();\r\n    }\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> NullObjectMutex {\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock(){}\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock(){}\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">NoLock<\/span>{\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        nullObjectMutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"NoLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n         nullObjectMutex.lock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> NullObjectMutex nullObjectMutex;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ExclusiveLock<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::lock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.lock();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"    ExclusiveLock::unlock: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        mutex.unlock();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>mutex mutex;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">SharedLock<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> lock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::lock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.lock_shared();\r\n    }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> unlock() <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"        SharedLock::unlock_shared: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n        sharedMutex.unlock_shared();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">mutable<\/span> std<span style=\"color: #555555;\">::<\/span>shared_mutex sharedMutex;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    \r\n    NoLock noLock;\r\n    StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>NoLock<span style=\"color: #555555;\">&gt;<\/span> stratLock1{noLock};\r\n    \r\n    {\r\n        ExclusiveLock exLock;\r\n        StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>ExclusiveLock<span style=\"color: #555555;\">&gt;<\/span> stratLock2{exLock};\r\n        {\r\n            SharedLock sharLock;\r\n            StrategizedLocking<span style=\"color: #555555;\">&lt;<\/span>SharedLock<span style=\"color: #555555;\">&gt;<\/span> startLock3{sharLock};\r\n        }\r\n    }\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>BasicLockable in line (1) requires that an object lo of the type <code>T<\/code> that it has to support the member functions lock and unlock. The use of the concept is straightforward. Instead of <code>typename<\/code>, I use the concept <code>BasicLockable<\/code> in the template declaration of <code>StrategizedLocking<\/code> (line 2).<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>To use your user-defined type in a range-based for-loop, you have to implement the Iterator Protocol. Let me discuss the details in my next post.<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Null Object encapsulates a do nothing behavior inside an object. It is often pretty comfortable to use a neutral object.<\/p>\n","protected":false},"author":21,"featured_media":6503,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[379],"tags":[402],"class_list":["post-6513","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-patterns","tag-policy"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6513","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=6513"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6513\/revisions"}],"predecessor-version":[{"id":8109,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6513\/revisions\/8109"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6503"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}