Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alternative async_send using logger #282

Closed
wants to merge 9 commits into from

Conversation

magni-mar
Copy link
Contributor

No description provided.

@magni-mar magni-mar requested a review from omarhogni November 22, 2023 11:56
libs/ipc/inc/public/tfc/ipc.hpp Outdated Show resolved Hide resolved
@@ -193,6 +193,17 @@ class signal {
return signal_->async_send(value, std::forward<completion_token_t>(token));
}

template <typename logger_t>
auto async_send(logger_t& logger) -> std::function<void(value_t)> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm 🤔 why return a function? I would rather like it being void.
Ex.
async_send(true, logger_);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like the function return. The lifetime of the function is then on the caller side and
you don't end up referencing a logger inside ipc that has a questionable lifetime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @omarhogni , ready to merge?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope if it returns a function it is not async_send

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like the function return. The lifetime of the function is then on the caller side and you don't end up referencing a logger inside ipc that has a questionable lifetime.

With this implementation you are keeping the reference of the signal within the lambda closure, so you can end up with dangling reference in both cases. So this impl does not solve safety.

As you know the safe way would be weak_ptr, either the signal would be stored as weak_ptr or the logger instance. I am still more inclined to the logger being passed and directly executated async_send.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct, I implemented the function with the logger being a weak_ptr and the async_send being called directly. Please see changes.

Copy link
Contributor

@jbbjarnason jbbjarnason Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions:

auto async_send(auto&& value, is_logger auto&& logger) -> void {
  static_assert(std::is_lvalue_reference_v<decltype(logger)>);
  return async_send(std::forward<decltype(value)>(value), [&logger, name = name()](std::error_code err, std::size_t){
    if (err) {
      logger.warn("{} unable to send reason: {}", name, err.message());
   }
  }
}
// or
// this is safe
template<is_logger logger_t>
auto async_send(auto&& value, std::weak_ptr<logger_t> logger) -> void {
  return async_send(std::forward<decltype(value)>(value), [logger,  name = name()](std::error_code err, std::size_t){
    if (err) {
      if (auto lock{ logger.lock() }) {
        logger->warn("{} unable to send reason: {}", name, err.message());
      } else {
        fmt::print(stderr, "{} unable to send reason: {}", name, err.message());
      }
   }
  }
}
// or 
auto async_send(auto&& value) -> void {
  return async_send(std::forward<decltype(value)>(value), [name = name()](std::error_code err, std::size_t){
    if (err) {
      logger::warn("{} unable to send reason: {}", name, err.message()); // static function call to exported logger func
   }
  }
}
// or 
auto async_send(auto&& value) -> void {
  return async_send(std::forward<decltype(value)>(value), [name = name()](std::error_code err, std::size_t){
    if (err) {
      fmt::print(stderr, "{} unable to send reason: {}", name, err.message()); // static function call to exported logger func
   }
  }
}
// or
// this is safe, but requires probably refactoring of many classes
auto make_callable_async_send(std::weak_ptr<logger_t> logger)  -> std::function<void(value_t)> {
  return [self = weak_from_this(), logger](value_t const& value){
    if (auto self_lock{ self.lock() }) {
      self_lock->async_send .....
    }
  };
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@omarhogni , would you like some of the above suggestions or should we close this?

@magni-mar magni-mar requested a review from omarhogni November 22, 2023 12:32
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@jbbjarnason
Copy link
Contributor

will be discussed later if needed

@jbbjarnason jbbjarnason closed this Jun 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants