cnstream_collection.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*************************************************************************
  2. * Copyright (C) [2021] by Cambricon, Inc. All rights reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  13. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  15. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. * THE SOFTWARE.
  19. *************************************************************************/
  20. #ifndef CNSTREAM_COLLECTION_HPP_
  21. #define CNSTREAM_COLLECTION_HPP_
  22. #include <memory>
  23. #include <mutex>
  24. #include <string>
  25. #include <unordered_map>
  26. #include <utility>
  27. #include "cnstream_common.hpp"
  28. #include "cnstream_logging.hpp"
  29. #include "util/cnstream_any.hpp"
  30. namespace cnstream {
  31. /**
  32. * @class Collection
  33. *
  34. * @brief Collection is a class storing structured data of variable types.
  35. *
  36. * @note This class is thread safe.
  37. */
  38. class Collection : public NonCopyable {
  39. public:
  40. /*!
  41. * @brief Constructs an instance with empty value.
  42. *
  43. * @return No return value.
  44. */
  45. Collection() = default;
  46. /*!
  47. * @brief Destructs an instance.
  48. *
  49. * @return No return value.
  50. */
  51. ~Collection() = default;
  52. /**
  53. * @brief Gets the reference to the object of typename ValueT if it exists, otherwise crashes.
  54. *
  55. * @param[in] tag The unique identifier of the data.
  56. *
  57. * @return Returns the reference to the object of typename ValueT which is tagged by `tag`.
  58. */
  59. template <typename ValueT>
  60. ValueT& Get(const std::string& tag);
  61. /**
  62. * @brief Adds data tagged by `tag`. Crashes when there is already a piece of data tagged by `tag`.
  63. *
  64. * @param[in] tag The unique identifier of the data.
  65. * @param[in] value Value to be add.
  66. *
  67. * @return Returns the reference to the object of typename ValueT which is tagged by `tag`.
  68. */
  69. template <typename ValueT>
  70. ValueT& Add(const std::string& tag, const ValueT& value);
  71. /**
  72. * @brief Adds data tagged by `tag` using move semantics. Crashes when there is already a piece of data tagged by
  73. * `tag`.
  74. *
  75. * @param[in] tag The unique identifier of the data.
  76. * @param[in] value Value to be add.
  77. *
  78. * @return Returns the reference to the object of typename ValueT which is tagged by `tag`.
  79. */
  80. template <typename ValueT>
  81. ValueT& Add(const std::string& tag, ValueT&& value);
  82. /**
  83. * @brief Adds data tagged by `tag`, only if there is no piece of data tagged by `tag`.
  84. *
  85. * @param[in] tag The unique identifier of the data.
  86. * @param[in] value Value to be add.
  87. *
  88. * @return Returns true if the data is added successfully, otherwise returns false.
  89. */
  90. template <typename ValueT>
  91. bool AddIfNotExists(const std::string& tag, const ValueT& value);
  92. /**
  93. * @brief Adds data tagged by `tag` using move semantics, only if there is no piece of data tagged by
  94. * `tag`.
  95. *
  96. * @param[in] tag The unique identifier of the data.
  97. * @param[in] value Value to be add.
  98. *
  99. * @return Returns true if the data is added successfully, otherwise returns false.
  100. */
  101. template <typename ValueT>
  102. bool AddIfNotExists(const std::string& tag, ValueT&& value);
  103. /**
  104. * @brief Checks whether there is the data tagged by `tag`.
  105. *
  106. * @param[in] tag The unique identifier of the data.
  107. *
  108. * @return Returns true if there is already a piece of data tagged by `tag`, otherwise returns false.
  109. */
  110. bool HasValue(const std::string& tag);
  111. #if !defined(_LIBCPP_NO_RTTI)
  112. /**
  113. * @brief Gets type information for data tagged by `tag`.
  114. *
  115. * @param[in] tag The unique identifier of the data.
  116. *
  117. * @return Returns type information of the data tagged by `tag`.
  118. */
  119. const std::type_info& Type(const std::string& tag);
  120. /**
  121. * @brief Checks if the type of data tagged by `tag` is `ValueT` or not.
  122. *
  123. * @param tag The unique identifier of the data.
  124. *
  125. * @return Returns true if the type of data tagged by `tag` is ``ValueT``, otherwise returns false.
  126. */
  127. template <typename ValueT>
  128. bool TaggedIsOfType(const std::string& tag);
  129. #endif
  130. private:
  131. void Add(const std::string& tag, std::unique_ptr<cnstream::any>&& value);
  132. bool AddIfNotExists(const std::string& tag, std::unique_ptr<cnstream::any>&& value);
  133. private:
  134. std::unordered_map<std::string, std::unique_ptr<cnstream::any>> data_;
  135. std::mutex data_mtx_;
  136. }; // class Collection
  137. template <typename ValueT>
  138. ValueT& Collection::Get(const std::string& tag) {
  139. std::lock_guard<std::mutex> lk(data_mtx_);
  140. auto iter = data_.find(tag);
  141. if (data_.end() == iter) {
  142. LOGF(COLLECTION) << "No data tagged by [" << tag << "] has been added.";
  143. }
  144. try {
  145. return any_cast<ValueT&>(*iter->second);
  146. } catch (bad_any_cast& e) {
  147. #if !defined(_LIBCPP_NO_RTTI)
  148. LOGF(COLLECTION) << "The type of data tagged by [" << tag << "] is ["
  149. << iter->second->type().name()
  150. << "]. Expect type is [" << typeid(ValueT).name() << "].";
  151. #else
  152. LOGF(COLLECTION) << "The type of data tagged by [" << tag << "] is not the "
  153. "expected data type."
  154. #endif
  155. }
  156. // never be here.
  157. return any_cast<ValueT&>(*iter->second);
  158. }
  159. template <typename ValueT> inline
  160. ValueT& Collection::Add(const std::string& tag, const ValueT& value) {
  161. Add(tag, std::unique_ptr<cnstream::any>(new cnstream::any(value)));
  162. return Get<ValueT>(tag);
  163. }
  164. template <typename ValueT> inline
  165. ValueT& Collection::Add(const std::string& tag, ValueT&& value) {
  166. Add(tag, std::unique_ptr<cnstream::any>(new cnstream::any(std::forward<ValueT>(value))));
  167. return Get<ValueT>(tag);
  168. }
  169. template <typename ValueT> inline
  170. bool Collection::AddIfNotExists(const std::string& tag, const ValueT& value) {
  171. return AddIfNotExists(tag, std::unique_ptr<cnstream::any>(new cnstream::any(value)));
  172. }
  173. template <typename ValueT> inline
  174. bool Collection::AddIfNotExists(const std::string& tag, ValueT&& value) {
  175. return AddIfNotExists(tag, std::unique_ptr<cnstream::any>(new cnstream::any(std::forward<ValueT>(value))));
  176. }
  177. #if !defined(_LIBCPP_NO_RTTI)
  178. template <typename ValueT> inline
  179. bool Collection::TaggedIsOfType(const std::string& tag) {
  180. if (!HasValue(tag)) return false;
  181. return typeid(ValueT) == Type(tag);
  182. }
  183. #endif
  184. } // namespace cnstream
  185. #endif // CNSTREAM_COLLECTION_HPP_