+ * An enum to describe the "level" of a mutex. The supported levels are
+ * Unique - a normal mutex that supports only exclusive locking
+ * Shared - a shared mutex which has shared locking and unlocking functions;
+ * Upgrade - a mutex that has all the methods of the two above along with
+ * support for upgradable locking
+ */
+enum class MutexLevel { UNIQUE, SHARED, UPGRADE };
+
+/**
+ * A template dispatch mechanism that is used to determine the level of the
+ * mutex based on its interface. As decided by LockInterfaceDispatcher.
+ */
+template <bool is_unique, bool is_shared, bool is_upgrade>
+struct MutexLevelValueImpl;
+template <>
+struct MutexLevelValueImpl<true, false, false> {
+ static constexpr MutexLevel value = MutexLevel::UNIQUE;
+};
+template <>
+struct MutexLevelValueImpl<true, true, false> {
+ static constexpr MutexLevel value = MutexLevel::SHARED;
+};
+template <>
+struct MutexLevelValueImpl<true, true, true> {
+ static constexpr MutexLevel value = MutexLevel::UPGRADE;
+};
+
+/**
+ * An internal helper class to help identify the interface supported by the
+ * mutex. This is used in conjunction with the above MutexLevel
+ * specializations and the LockTraitsImpl to determine what functions are
+ * supported by objects of type Mutex
+ *
+ * The implementation uses SINAE in the return value with trailing return
+ * types to figure out what level a mutex is