1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.io.FileDescriptor; 13 14 import hunt.util.Common; 15 import hunt.Exceptions; 16 17 import std.container.array; 18 /** 19 * Instances of the file descriptor class serve as an opaque handle 20 * to the underlying machine-specific structure representing an 21 * open file, an open socket, or another source or sink of bytes. 22 * The main practical use for a file descriptor is to create a 23 * {@link FileInputStream} or {@link FileOutputStream} to contain it. 24 * 25 * <p>Applications should not create their own file descriptors. 26 * 27 * @author Pavani Diwanji 28 * @since JDK1.0 29 */ 30 final class FileDescriptor { 31 32 private int fd; 33 34 private long handle; 35 36 private Closeable parent; 37 private Array!Closeable otherParents; 38 private bool closed; 39 40 /** 41 * Constructs an (invalid) FileDescriptor 42 * object. 43 */ 44 this() { 45 fd = -1; 46 handle = -1; 47 } 48 49 shared static this() { 50 // initIDs(); 51 } 52 53 // Set up JavaIOFileDescriptorAccess in SharedSecrets 54 // static { 55 // sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess( 56 // new sun.misc.JavaIOFileDescriptorAccess() { 57 // void set(FileDescriptor obj, int fd) { 58 // obj.fd = fd; 59 // } 60 61 // int get(FileDescriptor obj) { 62 // return obj.fd; 63 // } 64 65 // void setHandle(FileDescriptor obj, long handle) { 66 // obj.handle = handle; 67 // } 68 69 // long getHandle(FileDescriptor obj) { 70 // return obj.handle; 71 // } 72 // } 73 // ); 74 // } 75 76 /** 77 * A handle to the standard input stream. Usually, this file 78 * descriptor is not used directly, but rather via the input stream 79 * known as {@code System.in}. 80 * 81 * @see java.lang.System#in 82 */ 83 // __gshared FileDescriptor inHandle = standardStream(0); 84 85 /** 86 * A handle to the standard output stream. Usually, this file 87 * descriptor is not used directly, but rather via the output stream 88 * known as {@code System.out}. 89 * @see java.lang.System#out 90 */ 91 // __gshared FileDescriptor outHandle = standardStream(1); 92 93 /** 94 * A handle to the standard error stream. Usually, this file 95 * descriptor is not used directly, but rather via the output stream 96 * known as {@code System.err}. 97 * 98 * @see java.lang.System#err 99 */ 100 // static final FileDescriptor err = standardStream(2); 101 102 /** 103 * Tests if this file descriptor object is valid. 104 * 105 * @return {@code true} if the file descriptor object represents a 106 * valid, open file, socket, or other active I/O connection; 107 * {@code false} otherwise. 108 */ 109 bool valid() { 110 return ((handle != -1) || (fd != -1)); 111 } 112 113 /** 114 * Force all system buffers to synchronize with the underlying 115 * device. This method returns after all modified data and 116 * attributes of this FileDescriptor have been written to the 117 * relevant device(s). In particular, if this FileDescriptor 118 * refers to a physical storage medium, such as a file in a file 119 * system, sync will not return until all in-memory modified copies 120 * of buffers associated with this FileDesecriptor have been 121 * written to the physical medium. 122 * 123 * sync is meant to be used by code that requires physical 124 * storage (such as a file) to be in a known state For 125 * example, a class that provided a simple transaction facility 126 * might use sync to ensure that all changes to a file caused 127 * by a given transaction were recorded on a storage medium. 128 * 129 * sync only affects buffers downstream of this FileDescriptor. If 130 * any in-memory buffering is being done by the application (for 131 * example, by a BufferedOutputStream object), those buffers must 132 * be flushed into the FileDescriptor (for example, by invoking 133 * OutputStream.flush) before that data will be affected by sync. 134 * 135 * @exception SyncFailedException 136 * Thrown when the buffers cannot be flushed, 137 * or because the system cannot guarantee that all the 138 * buffers have been synchronized with physical media. 139 * @since JDK1.1 140 */ 141 void sync() { 142 implementationMissing(false); 143 } 144 145 /* This routine initializes JNI field offsets for the class */ 146 private static void initIDs() { 147 implementationMissing(false); 148 } 149 150 private static long set(int d) { 151 implementationMissing(false); 152 return 0; 153 } 154 155 private static FileDescriptor standardStream(int fd) { 156 FileDescriptor desc = new FileDescriptor(); 157 desc.handle = set(fd); 158 return desc; 159 } 160 161 /* 162 * Package private methods to track referents. 163 * If multiple streams point to the same FileDescriptor, we cycle 164 * through the list of all referents and call close() 165 */ 166 167 /** 168 * Attach a Closeable to this FD for tracking. 169 * parent reference is added to otherParents when 170 * needed to make closeAll simpler. 171 */ 172 void attach(Closeable c) { 173 if (parent is null) { 174 // first caller gets to do this 175 parent = c; 176 } else if (otherParents.length == 0) { 177 // otherParents = new ArrayList<>(); 178 otherParents.insertBack(parent); 179 otherParents.insertBack(c); 180 } else { 181 otherParents.insertBack(c); 182 } 183 } 184 185 /** 186 * Cycle through all Closeables sharing this FD and call 187 * close() on each one. 188 * 189 * The caller closeable gets to call close0(). 190 */ 191 void closeAll(Closeable releaser) { 192 if (!closed) { 193 closed = true; 194 IOException ioe = null; 195 try { 196 Closeable c = releaser; 197 foreach (Closeable referent ; otherParents) { 198 try { 199 referent.close(); 200 } catch(IOException x) { 201 if (ioe is null) { 202 ioe = x; 203 } else { 204 ioe.next = x; 205 } 206 } 207 } 208 } catch(IOException ex) { 209 /* 210 * If releaser close() throws IOException 211 * add other exceptions as suppressed. 212 */ 213 if (ioe !is null) 214 ex.next = ioe; 215 ioe = ex; 216 } finally { 217 if (ioe !is null) 218 throw ioe; 219 } 220 } 221 } 222 }