package obus
Pure Ocaml implementation of the D-Bus protocol
Install
Dune Dependency
Authors
Maintainers
Sources
obus-1.2.5.tar.gz
md5=81eb1034c6ef4421a2368a9b352199de
sha512=4b540497188a7d78f4f14f94c6b7fdff47dd06436a34e650ff378dd77bb3e2acb7afd45cd72daf4ddba06e732e9944d560c2882dc37862f1b1f1bb6df37e6205
doc/src/obus/oBus_property.ml.html
Source file oBus_property.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
(* * oBus_property.ml * ---------------- * Copyright : (c) 2010, Jeremie Dimino <jeremie@dimino.org> * Licence : BSD3 * * This file is a part of obus, an ocaml implementation of D-Bus. *) let section = Lwt_log.Section.make "obus(property)" open Lwt.Infix open Lwt_react open OBus_interfaces.Org_freedesktop_DBus_Properties (* +-----------------------------------------------------------------+ | Types | +-----------------------------------------------------------------+ *) module String_map = Map.Make(String) type map = (OBus_context.t * OBus_value.V.single) String_map.t type monitor = OBus_proxy.t -> OBus_name.interface -> Lwt_switch.t -> map signal Lwt.t type ('a, 'access) t = { p_interface : OBus_name.interface; (* The interface of the property. *) p_member : OBus_name.member; (* The name of the property. *) p_proxy : OBus_proxy.t; (* The object owning the property. *) p_monitor : monitor; (* Monitor for this property. *) p_cast : OBus_context.t -> OBus_value.V.single -> 'a; p_make : 'a -> OBus_value.V.single; } type 'a r = ('a, [ `readable ]) t type 'a w = ('a, [ `writable ]) t type 'a rw = ('a, [ `readable | `writable ]) t type group = { g_interface : OBus_name.interface; (* The interface of the group *) g_proxy : OBus_proxy.t; (* The object owning the group of properties *) g_monitor : monitor; (* Monitor for this group. *) } module Group_map = Map.Make (struct type t = OBus_name.bus * OBus_path.t * OBus_name.interface (* Groups are indexed by: - name of the owner of the property - path of the object owning the property - interfaec of the property *) let compare = Stdlib.compare end) (* Type of a cache for a group *) type cache = { mutable c_count : int; (* Numbers of monitored properties using this group. *) c_map : map signal; (* The signal holding the current state of properties. *) c_switch : Lwt_switch.t; (* Switch for the signal used to monitor the group. *) } type info = { mutable cache : cache Lwt.t Group_map.t; (* Cache of all monitored properties. *) } (* +-----------------------------------------------------------------+ | Default monitor | +-----------------------------------------------------------------+ *) let update_map context dict map = List.fold_left (fun map (name, value) -> String_map.add name (context, value) map) map dict let map_of_list context dict = update_map context dict String_map.empty let get_all_no_cache proxy interface = OBus_method.call_with_context m_GetAll proxy interface let default_monitor proxy interface switch = let%lwt event = OBus_signal.connect ~switch (OBus_signal.with_filters (OBus_match.make_arguments [(0, OBus_match.AF_string interface)]) (OBus_signal.with_context (OBus_signal.make s_PropertiesChanged proxy))) and context, dict = get_all_no_cache proxy interface in Lwt.return (S.map snd (S.fold_s ~eq:(fun (_, a) (_, b) -> String_map.equal (=) a b) (fun (_, map) (sig_context, (interface, updates, invalidates)) -> if invalidates = [] then Lwt.return (sig_context, update_map sig_context updates map) else let%lwt context, dict = get_all_no_cache proxy interface in Lwt.return (sig_context, map_of_list context dict)) (context, map_of_list context dict) event)) (* +-----------------------------------------------------------------+ | Property creation | +-----------------------------------------------------------------+ *) let make ?(monitor=default_monitor) desc proxy = { p_interface = OBus_member.Property.interface desc; p_member = OBus_member.Property.member desc; p_proxy = proxy; p_monitor = monitor; p_cast = (fun context value -> OBus_value.C.cast_single (OBus_member.Property.typ desc) value); p_make = (OBus_value.C.make_single (OBus_member.Property.typ desc)); } let group ?(monitor=default_monitor) proxy interface = { g_proxy = proxy; g_interface = interface; g_monitor = monitor; } (* +-----------------------------------------------------------------+ | Transformations | +-----------------------------------------------------------------+ *) let map_rw f g property = { property with p_cast = (fun context x -> f (property.p_cast context x)); p_make = (fun x -> property.p_make (g x)); } let map_rw_with_context f g property = { property with p_cast = (fun context x -> f context (property.p_cast context x)); p_make = (fun x -> property.p_make (g x)); } let map_r f property = { property with p_cast = (fun context x -> f (property.p_cast context x)); p_make = (fun x -> assert false); } let map_r_with_context f property = { property with p_cast = (fun context x -> f context (property.p_cast context x)); p_make = (fun x -> assert false); } let map_w g property = { property with p_cast = (fun context x -> assert false); p_make = (fun x -> property.p_make (g x)); } (* +-----------------------------------------------------------------+ | Operations on maps | +-----------------------------------------------------------------+ *) let find property map = let context, value = String_map.find property.p_member map in property.p_cast context value let find_with_context property map = let context, value = String_map.find property.p_member map in (context, property.p_cast context value) let find_value name map = let context, value = String_map.find name map in value let find_value_with_context name map = String_map.find name map let print_map pp map = let open Format in pp_open_box pp 2; pp_print_string pp "{"; pp_print_cut pp (); pp_open_hvbox pp 0; String_map.iter (fun name (context, value) -> pp_open_box pp 0; pp_print_string pp name; pp_print_space pp (); pp_print_string pp "="; pp_print_space pp (); OBus_value.V.print_single pp value; pp_print_string pp ";"; pp_close_box pp (); pp_print_cut pp ()) map; pp_close_box pp (); pp_print_cut pp (); pp_print_string pp "}"; pp_close_box pp () let string_of_map map = let open Format in let buf = Buffer.create 42 in let pp = formatter_of_buffer buf in pp_set_margin pp max_int; print_map pp map; pp_print_flush pp (); Buffer.contents buf (* +-----------------------------------------------------------------+ | Properties reading/writing | +-----------------------------------------------------------------+ *) let key = OBus_connection.new_key () let get_with_context prop = match OBus_connection.get (OBus_proxy.connection prop.p_proxy) key with | Some info -> begin match try Some(Group_map.find (OBus_proxy.name prop.p_proxy, OBus_proxy.path prop.p_proxy, prop.p_interface) info.cache) with Not_found -> None with | Some cache_thread -> let%lwt cache = cache_thread in Lwt.return (find_with_context prop (S.value cache.c_map)) | None -> let%lwt context, value = OBus_method.call_with_context m_Get prop.p_proxy (prop.p_interface, prop.p_member) in Lwt.return (context, prop.p_cast context value) end | None -> let%lwt context, value = OBus_method.call_with_context m_Get prop.p_proxy (prop.p_interface, prop.p_member) in Lwt.return (context, prop.p_cast context value) let get prop = get_with_context prop >|= snd let set prop value = OBus_method.call m_Set prop.p_proxy (prop.p_interface, prop.p_member, prop.p_make value) let get_group group = match OBus_connection.get (OBus_proxy.connection group.g_proxy) key with | Some info -> begin match try Some(Group_map.find (OBus_proxy.name group.g_proxy, OBus_proxy.path group.g_proxy, group.g_interface) info.cache) with Not_found -> None with | Some cache_thread -> let%lwt cache = cache_thread in Lwt.return (S.value cache.c_map) | None -> let%lwt context, dict = get_all_no_cache group.g_proxy group.g_interface in Lwt.return (map_of_list context dict) end | None -> let%lwt context, dict = get_all_no_cache group.g_proxy group.g_interface in Lwt.return (map_of_list context dict) (* +-----------------------------------------------------------------+ | Monitoring | +-----------------------------------------------------------------+ *) let finalise disable _ = ignore (Lazy.force disable) let monitor_group ?switch group = Lwt_switch.check switch; let cache_key = (OBus_proxy.name group.g_proxy, OBus_proxy.path group.g_proxy, group.g_interface) in let info = match OBus_connection.get (OBus_proxy.connection group.g_proxy) key with | Some info -> info | None -> let info = { cache = Group_map.empty } in OBus_connection.set (OBus_proxy.connection group.g_proxy) key (Some info); info in let%lwt cache = match try Some(Group_map.find cache_key info.cache) with Not_found -> None with | Some cache_thread -> cache_thread | None -> let waiter, wakener = Lwt.wait () in info.cache <- Group_map.add cache_key waiter info.cache; let switch = Lwt_switch.create () in try%lwt let%lwt signal = group.g_monitor group.g_proxy group.g_interface switch in let cache = { c_count = 0; c_map = signal; c_switch = switch; } in Lwt.wakeup wakener cache; Lwt.return cache with exn -> info.cache <- Group_map.remove cache_key info.cache; Lwt.wakeup_exn wakener exn; let%lwt () = Lwt_switch.turn_off switch in Lwt.fail exn in cache.c_count <- cache.c_count + 1; let disable = lazy( try%lwt cache.c_count <- cache.c_count - 1; if cache.c_count = 0 then begin info.cache <- Group_map.remove cache_key info.cache; Lwt_switch.turn_off cache.c_switch end else Lwt.return () with exn -> let%lwt () = Lwt_log.warning_f ~section ~exn "failed to disable monitoring of properties for interface %S on object %S from %S" group.g_interface (OBus_path.to_string (OBus_proxy.path group.g_proxy)) (OBus_proxy.name group.g_proxy) in Lwt.fail exn ) in let signal = S.with_finaliser (finalise disable) cache.c_map in let%lwt () = Lwt_switch.add_hook_or_exec switch (fun () -> S.stop signal; Lazy.force disable) in Lwt.return signal let monitor ?switch prop = let%lwt signal = monitor_group ?switch { g_interface = prop.p_interface; g_proxy = prop.p_proxy; g_monitor = prop.p_monitor } in Lwt.return (S.map (find prop) signal)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>