Browse Source

change : close file with async

Akeit0 6 months ago
parent
commit
0e8e56d427

+ 1 - 1
src/Lua/IO/ILuaStream.cs

@@ -79,7 +79,7 @@
         }
 
 
-        public ValueTask CloseAsync()
+        public ValueTask CloseAsync(CancellationToken cancellationToken)
         {
             Dispose();
             return default;

+ 1 - 1
src/Lua/IO/StandardIOStream.cs

@@ -37,7 +37,7 @@
             throw new IOException("cannot close standard file");
         }
 
-        public ValueTask CloseAsync()
+        public ValueTask CloseAsync(CancellationToken cancellationToken)
         {
             throw new IOException("cannot close standard file");
         }

+ 22 - 15
src/Lua/Standard/FileHandle.cs

@@ -22,6 +22,7 @@ public class FileHandle : ILuaUserData
                 "seek" => SeekFunction!,
                 "setvbuf" => SetVBufFunction!,
                 "write" => WriteFunction!,
+
                 _ => LuaValue.Nil,
             }));
         }
@@ -32,9 +33,8 @@ public class FileHandle : ILuaUserData
     });
 
     ILuaStream stream;
-    bool isClosed;
 
-    public bool IsClosed => Volatile.Read(ref isClosed);
+    public bool IsOpen => stream?.IsOpen ?? false;
 
     LuaTable? ILuaUserData.Metatable { get => fileHandleMetatable; set => fileHandleMetatable = value; }
 
@@ -44,6 +44,7 @@ public class FileHandle : ILuaUserData
     {
         fileHandleMetatable = new LuaTable(0, 1);
         fileHandleMetatable[Metamethods.Index] = IndexMetamethod;
+        fileHandleMetatable["__tostring"] = ToStringFunction;
     }
 
     public FileHandle(Stream stream, LuaFileOpenMode mode) : this(ILuaStream.CreateFromStream(stream, mode)) { }
@@ -52,12 +53,13 @@ public class FileHandle : ILuaUserData
     {
         this.stream = stream;
     }
+
     public ValueTask<double?> ReadNumberAsync(CancellationToken cancellationToken)
     {
-        return stream.ReadNumberAsync( cancellationToken);
+        return stream.ReadNumberAsync(cancellationToken);
     }
 
-    public ValueTask<string?> ReadLineAsync(bool keepEol,CancellationToken cancellationToken)
+    public ValueTask<string?> ReadLineAsync(bool keepEol, CancellationToken cancellationToken)
     {
         return stream.ReadLineAsync(keepEol, cancellationToken);
     }
@@ -87,9 +89,9 @@ public class FileHandle : ILuaUserData
     public long Seek(string whence, long offset) =>
         whence switch
         {
-            "set" => stream.Seek(SeekOrigin.Begin,offset),
-            "cur" => stream.Seek(SeekOrigin.Current,offset),
-            "end" => stream.Seek( SeekOrigin.End,offset),
+            "set" => stream.Seek(SeekOrigin.Begin, offset),
+            "cur" => stream.Seek(SeekOrigin.Current, offset),
+            "end" => stream.Seek(SeekOrigin.End, offset),
             _ => throw new ArgumentException($"Invalid option '{whence}'")
         };
 
@@ -110,26 +112,25 @@ public class FileHandle : ILuaUserData
         stream.SetVBuf(bufferingMode, size);
     }
 
-    public void Close()
+    public async ValueTask Close(CancellationToken cancellationToken)
     {
-        if (isClosed) throw new ObjectDisposedException(nameof(FileHandle));
-        stream.CloseAsync().AsTask().Wait();
-        Volatile.Write(ref isClosed, true);
+        if (!stream.IsOpen) throw new ObjectDisposedException(nameof(FileHandle));
+        await stream.CloseAsync(cancellationToken);
         stream = null!;
     }
 
-    static readonly LuaFunction CloseFunction = new("close", (context, cancellationToken) =>
+    static readonly LuaFunction CloseFunction = new("close", async (context, cancellationToken) =>
     {
         var file = context.GetArgument<FileHandle>(0);
 
         try
         {
-            file.Close();
-            return new(context.Return(true));
+            await file.Close(cancellationToken);
+            return context.Return(true);
         }
         catch (IOException ex)
         {
-            return new(context.Return(LuaValue.Nil, ex.Message, ex.HResult));
+            return context.Return(LuaValue.Nil, ex.Message, ex.HResult);
         }
     });
 
@@ -219,4 +220,10 @@ public class FileHandle : ILuaUserData
         var resultCount = await IOHelper.WriteAsync(file, "io.write", context with { ArgumentCount = context.ArgumentCount - 1 }, cancellationToken);
         return resultCount;
     });
+
+    static readonly LuaFunction ToStringFunction = new("file.__tostring", (context, cancellationToken) =>
+    {
+        var file = context.GetArgument<FileHandle>(0);
+        return new(context.Return($"file ({(file.IsOpen ? file.stream.GetHashCode() : "closed")})"));
+    });
 }

+ 7 - 7
src/Lua/Standard/IOLibrary.cs

@@ -28,7 +28,7 @@ public sealed class IOLibrary
 
     public readonly LibraryFunction[] Functions;
 
-    public ValueTask<int> Close(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
+    public async ValueTask<int> Close(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var file = context.HasArgument(0)
             ? context.GetArgument<FileHandle>(0)
@@ -36,12 +36,12 @@ public sealed class IOLibrary
 
         try
         {
-            file.Close();
-            return new(context.Return(true));
+            await file.Close(cancellationToken);
+            return context.Return(true);
         }
         catch (IOException ex)
         {
-            return new(context.Return(LuaValue.Nil, ex.Message, ex.HResult));
+            return context.Return(LuaValue.Nil, ex.Message, ex.HResult);
         }
     }
 
@@ -96,7 +96,7 @@ public sealed class IOLibrary
                 var resultCount = await IOHelper.ReadAsync(context.Thread, file, "io.lines", 0, Memory<LuaValue>.Empty, true, cancellationToken);
                 if (resultCount > 0 && context.Thread.Stack.Get(context.ReturnFrameBase).Type is LuaValueType.Nil)
                 {
-                    file.Close();
+                   await file.Close(cancellationToken);
                 }
 
                 return resultCount;
@@ -125,7 +125,7 @@ public sealed class IOLibrary
                 var resultCount = await IOHelper.ReadAsync(context.Thread, file, "io.lines", 0, formats, true, cancellationToken);
                 if (resultCount > 0 && stack.Get(context.ReturnFrameBase).Type is LuaValueType.Nil)
                 {
-                    file.Close();
+                  await  file.Close(cancellationToken);
                 }
 
                 return resultCount;
@@ -191,7 +191,7 @@ public sealed class IOLibrary
 
         if (arg0.TryRead<FileHandle>(out var file))
         {
-            return new(context.Return(file.IsClosed ? "closed file" : "file"));
+            return new(context.Return(file.IsOpen ? " file" :"closed file"));
         }
         else
         {