package hack_parallel
Parallel and shared memory library
Install
Dune Dependency
Authors
Maintainers
Sources
1.0.1.tar.gz
md5=ba7c72bc207e326b72e294fc76f6ad2c
sha512=5020d47f97bea2f88e2a40411894d03232a7f2282606926c93c7d4c96d72e94a966be852897a9b16f7e0893ba376512045abb9d93020a7c03c3def4f3d918f8e
doc/src/hack_parallel.utils/marshal_tools.ml.html
Source file marshal_tools.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
(** * Copyright (c) 2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the "hack" directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * *) (** * This tool allows for marshaling directly over file descriptors (instead of * ocaml "channels") to avoid buffering so that we can safely use marshaling * and libancillary together. * * The problem: * Ocaml's marshaling is done over channels, which have their own internal * buffer. This means after reading a marshaled object from a channel, the * FD's position is not guaranteed to be pointing to the beginning of the * next marshaled object (but instead points to the position after the * buffered read). So another process cannot receive this FD (over * libancillary) to start reading the next object. * * The solution: * Start each message with a fixed-size preamble that describes the * size of the payload to read. Read precisely that many bytes directly * from the FD avoiding Ocaml channels entirely. *) exception Invalid_Int_Size_Exception exception Payload_Size_Too_Large_Exception exception Malformed_Preamble_Exception exception Writing_Preamble_Exception exception Writing_Payload_Exception exception Reading_Preamble_Exception exception Reading_Payload_Exception (* We want to marshal exceptions (or at least their message+stacktrace) over *) (* the wire. This type ensures that no one will attempt to pattern-match on *) (* the thing we marshal: 'Values of extensible variant types, for example *) (* exceptions (of extensible type exn), returned by the unmarhsaller should *) (* not be pattern-matched over, because unmarshalling does not preserve the *) (* information required for matching their constructors.' *) (* https://caml.inria.fr/pub/docs/manual-ocaml/libref/Marshal.html *) type remote_exception_data = { message : string; stack : string; } let preamble_start_sentinel = '\142' (** Size in bytes. *) let preamble_core_size = 4 let expected_preamble_size = preamble_core_size + 1 (** Payload size in bytes = 2^31 - 1. *) let maximum_payload_size = (1 lsl (preamble_core_size * 8)) - 1 let get_preamble_core (size : int) = (* We limit payload size to 2^31 - 1 bytes. *) if size >= maximum_payload_size then raise Payload_Size_Too_Large_Exception; let rec loop i (remainder: int) acc = if i < 0 then acc else loop (i - 1) (remainder / 256) (Bytes.set acc i (Char.chr (remainder mod 256)); acc) in loop (preamble_core_size - 1) size (Bytes.create preamble_core_size) let make_preamble (size : int) = let preamble_core = get_preamble_core size in let preamble = Bytes.create (preamble_core_size + 1) in Bytes.set preamble 0 preamble_start_sentinel; Bytes.blit preamble_core 0 preamble 1 4; preamble let parse_preamble preamble = if (Bytes.length preamble) <> expected_preamble_size || (Bytes.get preamble 0) <> preamble_start_sentinel then raise Malformed_Preamble_Exception; let rec loop i acc = if i >= 5 then acc else loop (i + 1) ((acc * 256) + (int_of_char (Bytes.get preamble i))) in loop 1 0 let to_fd_with_preamble fd obj = let flag_list = [] in let payload = Marshal.to_bytes obj flag_list in let size = Bytes.length payload in let preamble = make_preamble size in let preamble_bytes_written = Unix.write fd preamble 0 expected_preamble_size in if preamble_bytes_written <> expected_preamble_size then raise Writing_Preamble_Exception; let bytes_written = Unix.write fd payload 0 size in if bytes_written <> size then raise Writing_Payload_Exception; () let rec read_payload fd buffer offset to_read = if to_read = 0 then offset else begin let bytes_read = Unix.read fd buffer offset to_read in if bytes_read = 0 then offset else begin read_payload fd buffer (offset+bytes_read) (to_read-bytes_read) end end let from_fd_with_preamble fd = let preamble = Bytes.create expected_preamble_size in let bytes_read = Unix.read fd preamble 0 expected_preamble_size in if (bytes_read = 0) (* Unix manpage for read says 0 bytes read indicates end of file. *) then raise End_of_file else if (bytes_read <> expected_preamble_size) then (Printf.eprintf "Error, only read %d bytes for preamble.\n" bytes_read; raise Reading_Preamble_Exception); let payload_size = parse_preamble preamble in let payload = Bytes.create payload_size in let payload_size_read = read_payload fd payload 0 payload_size in if (payload_size_read <> payload_size) then raise Reading_Payload_Exception; Marshal.from_bytes payload 0
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>