give all folly exception types default visibility
authorEric Niebler <eniebler@fb.com>
Mon, 8 Jan 2018 23:21:57 +0000 (15:21 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 8 Jan 2018 23:36:38 +0000 (15:36 -0800)
Summary: This makes sure that whether folly is statically or dynamically linked, all folly exception types will have exactly one definition, and one set of type information.

Reviewed By: mzlee

Differential Revision: D6671431

fbshipit-source-id: 1c06826a05f87cbf9af747c9abdb5f524744d054

22 files changed:
folly/AtomicHashMap.h
folly/ExceptionWrapper.h
folly/Expected.h
folly/Format.h
folly/FormatArg.h
folly/IPAddressException.h
folly/Optional.h
folly/Poly.h
folly/Subprocess.h
folly/Try.h
folly/dynamic-inl.h
folly/executors/task_queue/BlockingQueue.h
folly/experimental/DynamicParser.h
folly/experimental/EnvUtil.h
folly/experimental/JSONSchema.cpp
folly/experimental/NestedCommandLineApp.h
folly/experimental/bser/Bser.h
folly/experimental/logging/LogConfigParser.h
folly/fibers/AtomicBatchDispatcher.h
folly/io/async/AsyncSocketException.h
folly/json.cpp
folly/synchronization/LifoSem.h

index 2243b6b..cfa7810 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 /*
  * AtomicHashMap --
  *
@@ -91,6 +90,7 @@
 #include <stdexcept>
 
 #include <folly/AtomicHashArray.h>
+#include <folly/CPortability.h>
 #include <folly/Likely.h>
 #include <folly/ThreadCachedInt.h>
 #include <folly/container/Foreach.h>
@@ -149,7 +149,7 @@ namespace folly {
 
 // Thrown when insertion fails due to running out of space for
 // submaps.
-struct AtomicHashMapFullError : std::runtime_error {
+struct FOLLY_EXPORT AtomicHashMapFullError : std::runtime_error {
   explicit AtomicHashMapFullError()
     : std::runtime_error("AtomicHashMap is full")
   {}
index ff60aa3..fc0cac7 100644 (file)
@@ -162,7 +162,7 @@ auto fold(Fn&& fn, A&& a, B&& b, Bs&&... bs) {
 //! \endcode
 class exception_wrapper final {
  private:
-  struct AnyException : std::exception {
+  struct FOLLY_EXPORT AnyException : std::exception {
     std::type_info const* typeinfo_;
     template <class T>
     /* implicit */ AnyException(T&& t) noexcept : typeinfo_(&typeid(t)) {}
index 3796336..9d3535f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 /**
  * Like folly::Optional, but can store a value *or* an error.
  *
@@ -31,6 +30,7 @@
 
 #include <glog/logging.h>
 
+#include <folly/CPortability.h>
 #include <folly/CppAttributes.h>
 #include <folly/Likely.h>
 #include <folly/Optional.h>
@@ -660,7 +660,7 @@ inline expected_detail::UnexpectedTag unexpected(
 /**
  * An exception type thrown by Expected on catastrophic logic errors.
  */
-class BadExpectedAccess : public std::logic_error {
+class FOLLY_EXPORT BadExpectedAccess : public std::logic_error {
  public:
   BadExpectedAccess() : std::logic_error("bad Expected access") {}
 };
@@ -689,7 +689,7 @@ class Unexpected final : ColdClass {
    * when the user tries to access the nested value but the Expected object is
    * actually storing an error code.
    */
-  class BadExpectedAccess : public folly::BadExpectedAccess {
+  class FOLLY_EXPORT BadExpectedAccess : public folly::BadExpectedAccess {
    public:
     explicit BadExpectedAccess(Error err)
         : folly::BadExpectedAccess{}, error_(std::move(err)) {}
index 5980639..2c5f2fc 100644 (file)
@@ -22,6 +22,7 @@
 #include <tuple>
 #include <type_traits>
 
+#include <folly/CPortability.h>
 #include <folly/Conv.h>
 #include <folly/FormatArg.h>
 #include <folly/Range.h>
@@ -318,7 +319,7 @@ inline std::string svformat(StringPiece fmt, Container&& container) {
  * makes the exception type small and noexcept-copyable like std::out_of_range,
  * and therefore able to fit in-situ in exception_wrapper.
  */
-class FormatKeyNotFoundException : public std::out_of_range {
+class FOLLY_EXPORT FormatKeyNotFoundException : public std::out_of_range {
  public:
   explicit FormatKeyNotFoundException(StringPiece key);
 
index df1054e..62c9705 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdexcept>
 
+#include <folly/CPortability.h>
 #include <folly/Conv.h>
 #include <folly/Likely.h>
 #include <folly/Portability.h>
@@ -25,7 +26,7 @@
 
 namespace folly {
 
-class BadFormatArg : public std::invalid_argument {
+class FOLLY_EXPORT BadFormatArg : public std::invalid_argument {
   using invalid_argument::invalid_argument;
 };
 
index d1830ba..0ba7462 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <exception>
 #include <string>
 #include <utility>
 
+#include <folly/CPortability.h>
 #include <folly/detail/IPAddress.h>
 
 namespace folly {
@@ -32,7 +32,7 @@ enum class IPAddressFormatError { INVALID_IP, UNSUPPORTED_ADDR_FAMILY };
 /**
  * Exception for invalid IP addresses.
  */
-class IPAddressFormatException : public std::exception {
+class FOLLY_EXPORT IPAddressFormatException : public std::exception {
  public:
   explicit IPAddressFormatException(std::string msg) noexcept
       : msg_(std::move(msg)) {}
@@ -51,7 +51,8 @@ class IPAddressFormatException : public std::exception {
   std::string msg_;
 };
 
-class InvalidAddressFamilyException : public IPAddressFormatException {
+class FOLLY_EXPORT InvalidAddressFamilyException
+    : public IPAddressFormatException {
  public:
   explicit InvalidAddressFamilyException(std::string msg) noexcept
       : IPAddressFormatException(std::move(msg)) {}
index 60ae2c7..8f48010 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 /*
@@ -87,7 +86,7 @@ typedef int detail::NoneHelper::*None;
 
 const None none = nullptr;
 
-class OptionalEmptyException : public std::runtime_error {
+class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error {
  public:
   OptionalEmptyException()
       : std::runtime_error("Empty Optional cannot be unwrapped") {}
index 5563f0a..f2f4b90 100644 (file)
@@ -35,6 +35,7 @@
 #include <typeinfo>
 #include <utility>
 
+#include <folly/CPortability.h>
 #include <folly/CppAttributes.h>
 #include <folly/Traits.h>
 #include <folly/detail/TypeList.h>
@@ -175,7 +176,7 @@ struct PolyMembers {};
 /**
  * Exception type that is thrown on invalid access of an empty `Poly` object.
  */
-struct BadPolyAccess : std::exception {
+struct FOLLY_EXPORT BadPolyAccess : std::exception {
   BadPolyAccess() = default;
   char const* what() const noexcept override {
     return "BadPolyAccess";
@@ -186,7 +187,7 @@ struct BadPolyAccess : std::exception {
  * Exception type that is thrown when attempting to extract from a `Poly` a
  * value of the wrong type.
  */
-struct BadPolyCast : std::bad_cast {
+struct FOLLY_EXPORT BadPolyCast : std::bad_cast {
   BadPolyCast() = default;
   char const* what() const noexcept override {
     return "BadPolyCast";
index 72cf3fe..597bb57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 /**
  * Subprocess library, modeled after Python's subprocess module
  * (http://docs.python.org/2/library/subprocess.html)
@@ -219,7 +218,7 @@ class ProcessReturnCode {
 /**
  * Base exception thrown by the Subprocess methods.
  */
-class SubprocessError : public std::runtime_error {
+class FOLLY_EXPORT SubprocessError : public std::runtime_error {
  public:
   using std::runtime_error::runtime_error;
 };
@@ -227,7 +226,7 @@ class SubprocessError : public std::runtime_error {
 /**
  * Exception thrown by *Checked methods of Subprocess.
  */
-class CalledProcessError : public SubprocessError {
+class FOLLY_EXPORT CalledProcessError : public SubprocessError {
  public:
   explicit CalledProcessError(ProcessReturnCode rc);
   ~CalledProcessError() throw() override = default;
@@ -239,7 +238,7 @@ class CalledProcessError : public SubprocessError {
 /**
  * Exception thrown if the subprocess cannot be started.
  */
-class SubprocessSpawnError : public SubprocessError {
+class FOLLY_EXPORT SubprocessSpawnError : public SubprocessError {
  public:
   SubprocessSpawnError(const char* executable, int errCode, int errnoValue);
   ~SubprocessSpawnError() throw() override = default;
index 7b97754..6175349 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <folly/ExceptionWrapper.h>
 
 namespace folly {
 
-class TryException : public std::logic_error {
+class FOLLY_EXPORT TryException : public std::logic_error {
  public:
   using std::logic_error::logic_error;
 };
 
-class UsingUninitializedTry : public TryException {
+class FOLLY_EXPORT UsingUninitializedTry : public TryException {
  public:
   UsingUninitializedTry() : TryException("Using uninitialized try") {}
 };
index 7b187d7..b82126f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <functional>
@@ -21,6 +20,7 @@
 #include <boost/iterator/iterator_adaptor.hpp>
 #include <boost/iterator/iterator_facade.hpp>
 
+#include <folly/CPortability.h>
 #include <folly/Conv.h>
 #include <folly/Format.h>
 #include <folly/Likely.h>
@@ -76,7 +76,7 @@ struct hash<::folly::dynamic> {
 
 namespace folly {
 
-struct TypeError : std::runtime_error {
+struct FOLLY_EXPORT TypeError : std::runtime_error {
   explicit TypeError(const std::string& expected, dynamic::Type actual);
   explicit TypeError(
       const std::string& expected,
index 4928095..99147ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <exception>
@@ -21,6 +20,8 @@
 
 #include <glog/logging.h>
 
+#include <folly/CPortability.h>
+
 namespace folly {
 
 // Some queue implementations (for example, LifoSemMPMCQueue or
@@ -28,7 +29,7 @@ namespace folly {
 // non-blocking (THROW) behaviors.
 enum class QueueBehaviorIfFull { THROW, BLOCK };
 
-class QueueFullException : public std::runtime_error {
+class FOLLY_EXPORT QueueFullException : public std::runtime_error {
   using std::runtime_error::runtime_error; // Inherit constructors.
 };
 
index 386eed3..57a5375 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
  */
 #pragma once
 
+#include <folly/CPortability.h>
 #include <folly/ScopeGuard.h>
 #include <folly/dynamic.h>
 
@@ -194,7 +195,7 @@ std::string toPseudoJson(const folly::dynamic& d);
  * With DynamicParser::OnError::THROW, reports the first error.
  * It is forbidden to call releaseErrors() if you catch this.
  */
-struct DynamicParserParseError : public std::runtime_error {
+struct FOLLY_EXPORT DynamicParserParseError : public std::runtime_error {
   explicit DynamicParserParseError(folly::dynamic error)
     : std::runtime_error(folly::to<std::string>(
         "DynamicParserParseError: ", detail::toPseudoJson(error)
@@ -217,7 +218,7 @@ struct DynamicParserParseError : public std::runtime_error {
  * instead of reporting an error via releaseErrors().  It is unsafe to call
  * any parser methods after catching a LogicError.
  */
-struct DynamicParserLogicError : public std::logic_error {
+struct FOLLY_EXPORT DynamicParserLogicError : public std::logic_error {
   template <typename... Args>
   explicit DynamicParserLogicError(Args&&... args)
     : std::logic_error(folly::to<std::string>(std::forward<Args>(args)...)) {}
index 2d22f29..101966f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
-#include <folly/Memory.h>
 #include <map>
 #include <string>
 #include <unordered_map>
 #include <vector>
 
+#include <folly/CPortability.h>
+#include <folly/Memory.h>
+
 namespace folly {
 namespace experimental {
 
@@ -87,7 +88,7 @@ struct EnvironmentState {
   EnvType env_;
 };
 
-struct MalformedEnvironment : std::runtime_error {
+struct FOLLY_EXPORT MalformedEnvironment : std::runtime_error {
   using std::runtime_error::runtime_error;
 };
 } // namespace experimental
index d739fd1..5d7f502 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include <folly/experimental/JSONSchema.h>
 
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/regex.hpp>
+
+#include <folly/CPortability.h>
 #include <folly/Conv.h>
 #include <folly/Memory.h>
 #include <folly/Optional.h>
@@ -33,8 +34,7 @@ namespace {
 /**
  * We throw this exception when schema validation fails.
  */
-struct SchemaError : std::runtime_error {
-
+struct FOLLY_EXPORT SchemaError : std::runtime_error {
   SchemaError(SchemaError&&) = default;
   SchemaError(const SchemaError&) = default;
 
index 2421034..a5e3d5e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <functional>
 #include <stdexcept>
 
+#include <folly/CPortability.h>
 #include <folly/experimental/ProgramOptions.h>
 
 namespace folly {
@@ -30,7 +30,7 @@ namespace folly {
  * empty; the message is only allowed when exiting with a non-zero status), and
  * return the exit code. (Other exceptions will propagate out of run())
  */
-class ProgramExit : public std::runtime_error {
+class FOLLY_EXPORT ProgramExit : public std::runtime_error {
  public:
   explicit ProgramExit(int status, const std::string& msg = std::string());
   int status() const { return status_; }
index 571a7fd..571e3f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 #pragma once
+#include <folly/CPortability.h>
 #include <folly/Optional.h>
 #include <folly/dynamic.h>
 #include <folly/io/IOBuf.h>
@@ -32,7 +33,7 @@
 namespace folly {
 namespace bser {
 
-class BserDecodeError : public std::runtime_error {
+class FOLLY_EXPORT BserDecodeError : public std::runtime_error {
  public:
   using std::runtime_error::runtime_error;
 };
index fae3863..d677631 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <stdexcept>
 
+#include <folly/CPortability.h>
 #include <folly/Range.h>
 #include <folly/experimental/logging/LogConfig.h>
 
@@ -34,7 +35,7 @@ namespace folly {
 
 struct dynamic;
 
-class LogConfigParseError : public std::invalid_argument {
+class FOLLY_EXPORT LogConfigParseError : public std::invalid_argument {
  public:
   using std::invalid_argument::invalid_argument;
 };
index 93f9c93..6dfddd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 #pragma once
 
-#include <folly/Function.h>
-#include <folly/Optional.h>
-#include <folly/fibers/detail/AtomicBatchDispatcher.h>
-#include <folly/futures/Future.h>
-#include <folly/futures/Promise.h>
 #include <memory>
 #include <stdexcept>
 #include <string>
 #include <utility>
 #include <vector>
 
+#include <folly/CPortability.h>
+#include <folly/Function.h>
+#include <folly/Optional.h>
+#include <folly/fibers/detail/AtomicBatchDispatcher.h>
+#include <folly/futures/Future.h>
+#include <folly/futures/Promise.h>
+
 namespace folly {
 namespace fibers {
 
@@ -35,7 +37,7 @@ namespace fibers {
  * Examples are, multiple dispatch calls on the same token, trying to get more
  * tokens from the dispatcher after commit has been called, etc.
  */
-class ABDUsageException : public std::logic_error {
+class FOLLY_EXPORT ABDUsageException : public std::logic_error {
   using std::logic_error::logic_error;
 };
 
@@ -43,7 +45,7 @@ class ABDUsageException : public std::logic_error {
  * An exception class that gets set on the promise for dispatched tokens, when
  * the AtomicBatchDispatcher was destroyed before commit was called on it.
  */
-class ABDCommitNotCalledException : public std::runtime_error {
+class FOLLY_EXPORT ABDCommitNotCalledException : public std::runtime_error {
  public:
   ABDCommitNotCalledException()
       : std::runtime_error(
@@ -57,7 +59,7 @@ class ABDCommitNotCalledException : public std::runtime_error {
  * Only here so that the caller can distinguish the real failure cause
  * rather than these subsequently thrown exceptions.
  */
-class ABDTokenNotDispatchedException : public std::runtime_error {
+class FOLLY_EXPORT ABDTokenNotDispatchedException : public std::runtime_error {
   using std::runtime_error::runtime_error;
 };
 
index 83f95ee..1e9a114 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <stdexcept>
 #include <string>
 
+#include <folly/CPortability.h>
 #include <folly/Range.h>
 
 namespace folly {
 
-class AsyncSocketException : public std::runtime_error {
+class FOLLY_EXPORT AsyncSocketException : public std::runtime_error {
  public:
   enum AsyncSocketExceptionType {
     UNKNOWN = 0,
index db80b33..a9d7af9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include <folly/json.h>
 
 #include <algorithm>
 
 #include <boost/algorithm/string.hpp>
 #include <boost/next_prior.hpp>
-#include <folly/Portability.h>
-#include <folly/lang/Bits.h>
 
 #include <folly/Conv.h>
+#include <folly/Portability.h>
 #include <folly/Range.h>
 #include <folly/String.h>
 #include <folly/Unicode.h>
+#include <folly/lang/Bits.h>
 #include <folly/portability/Constexpr.h>
 
 namespace folly {
@@ -187,7 +186,7 @@ struct Printer {
 
 //////////////////////////////////////////////////////////////////////
 
-struct ParseError : std::runtime_error {
+struct FOLLY_EXPORT ParseError : std::runtime_error {
   explicit ParseError(
       unsigned int line,
       std::string const& context,
index 102154c..c6ed69b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <algorithm>
@@ -23,6 +22,7 @@
 #include <memory>
 #include <system_error>
 
+#include <folly/CPortability.h>
 #include <folly/CachelinePadded.h>
 #include <folly/IndexedMemPool.h>
 #include <folly/Likely.h>
@@ -90,7 +90,7 @@ typedef LifoSemImpl<> LifoSem;
 
 
 /// The exception thrown when wait()ing on an isShutdown() LifoSem
-struct ShutdownSemError : public std::runtime_error {
+struct FOLLY_EXPORT ShutdownSemError : public std::runtime_error {
   explicit ShutdownSemError(const std::string& msg);
   ~ShutdownSemError() noexcept override;
 };