A Null Object encapsulates a do nothing behavior inside an object. It is often pretty comfortable to use a neutral object.
A Null Object
- encapsulates the do nothing behavior inside an object.
- supports the workflow without conditional logic.
- hides the special use cases from the client.
Honestly, there is not much to write about the Null Object. Let me, therefore, give you an example, using a Null Object.
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.
Strategized locking is the idea of the Strategy Pattern applied to locking. This means putting your locking strategy into an object and making it into a pluggable component of your system.
There are two typical ways to implement strategized locking: run-time polymorphism (object orientation) or compile-time polymorphism (templates).
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.
- Allows it to configure the locking strategy during run time
- Is easier to understand for developers who have an object-oriented background
- Has no abstraction penalty
- Has a flat hierarchy.
- Needs an additional pointer or reference indirection
- It may have a deep derivation hierarchy
- It may generate very wordy error messages.
Implementation based on Run-Time Polymorphism
strategizedLockingRuntime.cpp presents three different mutexes.
StrategizedLocking has a lock (line 1).
StrategizedLocking models scoped locking and, therefore, locks the mutex in the constructor (line 2) and unlocks it in the destructor (line 3).
Lock is an abstract class and defines all derived classes’ interfaces. These are the classes
NoLock (line 4),
ExclusiveLock (line 5), and
SharedLock (line 6).
lock_shared (line 7) and
unlock_shared (line 8) on its
std::shared_mutex. Each of these locks holds one of the mutexes
NullObjectMutex (line 9),
std::mutex (line 10), or
std::shared_mutex (line 11).
NullObjectMutex is a noop placeholder. The mutexes are declared as
mutable. Therefore, they are usable in constant member functions such as
Implementation based on Compile-Time Polymorphism
The template-based implementation is quite similar to the object-oriented-based implementation.
strategizedLockingCompileTime.cpp produce the same output:
NoLock (line 1),
ExclusiveLock (line 2), and
SharedLock (line 3) have no abstract base class. The consequence is that
StrategizedLocking 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.
The Concept BasicLockable
template <typename Lock> class StrategizedLocking you can use the
template <BasicLockable Lock> class StrategizedLocking. This means that all used locks have to support the concept
BasicLockable. A concept is a named requirement, and many concepts are already defined in the C++20 concepts library. The concept
BasicLockable is only used in the text of the C++20 standard. Consequently, I define and use the concept
BasicLockable in the following improved implementation of the strategized locking at compile time.
BasicLockable in line (1) requires that an object lo of the type
T that it has to support the member functions lock and unlock. The use of the concept is straightforward. Instead of
typename, I use the concept
BasicLockable in the template declaration of
StrategizedLocking (line 2).
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.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,