blob: ede18152017f387b7178f0a39fe5887736fe3bc5 [file] [log] [blame]
mukesh agrawal0e9e9d12014-04-18 16:09:58 -07001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_DBUS_ASYNC_CALL_HELPER_H_
6#define SHILL_DBUS_ASYNC_CALL_HELPER_H_
7
8#include "shill/logging.h"
9
Ben Chand1fce552014-10-17 01:12:52 -070010#include <memory>
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070011#include <string>
Ben Chand1fce552014-10-17 01:12:52 -070012
Ben Chancc67c522014-09-03 07:19:18 -070013#include <base/macros.h> // for ignore_result
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070014#include <dbus-c++/error.h>
15
16#include "shill/error.h"
17
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070018using std::string;
19
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070020namespace shill {
21
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070022namespace Logging {
23static auto kModuleLogScope = ScopeLogger::kDBus;
Paul Stewarta794cd62015-06-16 13:13:10 -070024static string ObjectID(const DBus::Path* p) { return *p;}
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070025}
26
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070027// The dbus-c++ async call mechanism has a funny way of handling the
28// callback parameter. In particular, the caller is responsible for
29// cleaning up the callback. (This is unlike the low-level D-Bus
30// library, which accepts a function pointer for the cleanup
31// function.)
32//
33// In cases where the call completes asynchronously, we delete the
34// callback in the return-handling code. However, if the call
35// generates a synchronous error, we need to delete the callback
36// immediately.
37//
38// This template simply factors out that pattern, so that we don't
39// need to repeat the code in every async stub.
40
41template<
42 typename TraceMsgT, typename ProxyT, typename CallT,
43 typename CallbackT, typename... ArgTypes>
Paul Stewarta794cd62015-06-16 13:13:10 -070044void BeginAsyncDBusCall(const TraceMsgT& trace_msg,
45 ProxyT& proxy, // NOLINT(runtime/references)
46 const CallT& call, const CallbackT& callback,
47 Error* error,
48 void(*error_converter)(const DBus::Error&, Error*),
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070049 int timeout, ArgTypes... call_args) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070050 SLOG(&proxy.path(), 2) << trace_msg << " [timeout=" << timeout << "]";
Ben Chand1fce552014-10-17 01:12:52 -070051 std::unique_ptr<CallbackT> cb(new CallbackT(callback));
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070052 try {
53 (proxy.*call)(call_args..., cb.get(), timeout);
mukesh agrawal62ba51c2014-04-18 16:09:58 -070054 // We've successfully passed ownership of |cb| to |proxy|, so we
55 // must release() ownership. (Otherwise, |cb| will be deleted on
56 // return from this function.)
57 //
58 // Since we have no further need to reference the CallbackT in
59 // this scope, we ignore the return value of release(). Ignoring
60 // the return value is normally an error, because that means
61 // you're leaking the object. However, it's fine here, because
62 // |proxy| now owns |cb|.
63 ignore_result(cb.release());
Paul Stewarta794cd62015-06-16 13:13:10 -070064 } catch (const DBus::Error& e) {
mukesh agrawal0e9e9d12014-04-18 16:09:58 -070065 if (error)
66 error_converter(e, error);
67 }
68}
69
70} // namespace shill
71
72#endif // SHILL_DBUS_ASYNC_CALL_HELPER_H_