1// Copyright (c) Benjamin Kietzman (github.com/bkietz)
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef DBUS_CONNECTION_IPP
7#define DBUS_CONNECTION_IPP
8
9#include <dbus/dbus.h>
10#include <dbus/detail/watch_timeout.hpp>
11
12#include <boost/atomic.hpp>
13
14namespace dbus {
15namespace impl {
16
17class connection
18{
19public:
20  boost::atomic<bool> is_paused;
21  DBusConnection *conn;
22
23  connection()
24    : is_paused(true),
25      conn(NULL)
26  {
27  }
28
29  void open(boost::asio::io_service& io, int bus)
30  {
31    error e;
32    conn = dbus_bus_get_private((DBusBusType)bus, e);
33    e.throw_if_set();
34
35    dbus_connection_set_exit_on_disconnect(conn, false);
36
37    detail::set_watch_timeout_dispatch_functions(conn, io);
38  }
39
40  void open(boost::asio::io_service& io, const string& address)
41  {
42    error e;
43    conn = dbus_connection_open_private(address.c_str(), e);
44    e.throw_if_set();
45
46    dbus_bus_register(conn, e);
47    e.throw_if_set();
48
49    dbus_connection_set_exit_on_disconnect(conn, false);
50
51    detail::set_watch_timeout_dispatch_functions(conn, io);
52  }
53
54  ~connection()
55  {
56    if (conn != NULL) {
57      dbus_connection_close(conn);
58      dbus_connection_unref(conn);
59    }
60  }
61
62  operator DBusConnection *()
63  {
64    return conn;
65  }
66  operator const DBusConnection *() const
67  {
68    return conn;
69  }
70
71  message send_with_reply_and_block(message& m,
72      int timeout_in_milliseconds = -1)
73  {
74    error e;
75    message reply(dbus_connection_send_with_reply_and_block(conn,
76        m, timeout_in_milliseconds, e));
77
78    e.throw_if_set();
79    return reply;
80  }
81
82  void send(message& m)
83  {
84    // ignoring message serial for now
85    dbus_connection_send(conn, m, NULL);
86  }
87
88  void send_with_reply(message& m,
89      DBusPendingCall **p,
90      int timeout_in_milliseconds = -1)
91  {
92    dbus_connection_send_with_reply(conn,
93        m, p, timeout_in_milliseconds);
94  }
95
96  // begin asynchronous operation
97  //FIXME should not get io from an argument
98  void start(boost::asio::io_service& io)
99  {
100    bool old_value(true);
101    if(is_paused.compare_exchange_strong(old_value, false))
102    {
103      // If two threads call connection::async_send()
104      // simultaneously on a paused connection, then
105      // only one will pass the CAS instruction and
106      // only one dispatch_handler will be injected.
107      io.post(detail::dispatch_handler(io, conn));
108    }
109  }
110
111  void cancel(boost::asio::io_service& io)
112  {
113    bool old_value(false);
114    if(is_paused.compare_exchange_strong(old_value, true))
115    {
116      //TODO
117    }
118  }
119};
120
121} // namespace impl
122} // namespace dbus
123
124#endif // DBUS_CONNECTION_IPP
125