OSDN Git Service

セマフォーだとデッドロックを起こすことがあるのでリーダーライターロッカーに変更した
authortest <test@yahoo.co.jp>
Tue, 5 Feb 2019 11:54:24 +0000 (20:54 +0900)
committertest <test@yahoo.co.jp>
Tue, 5 Feb 2019 11:54:24 +0000 (20:54 +0900)
Core/Document.cs
Core/StringBuffer.cs

index 0a42405..ed6fdf3 100644 (file)
@@ -1160,30 +1160,11 @@ namespace FooEditEngine
         {
             try
             {
-                await this.buffer.LockAsync().ConfigureAwait(false);
-                StringBuilder line = new StringBuilder();
-                for (int i = 0; i < this.Length; i++)
-                {
-                    char c = this[i];
-                    line.Append(c);
-                    if (c == Document.NewLine || i == this.Length - 1)
-                    {
-                        string str = line.ToString();
-                        str = str.Replace(Document.NewLine.ToString(), fs.NewLine);
-                        await fs.WriteAsync(str).ConfigureAwait(false);
-                        line.Clear();
-                        if (tokenSource != null)
-                            tokenSource.Token.ThrowIfCancellationRequested();
-#if TEST_ASYNC
-                    System.Threading.Thread.Sleep(10);
-#endif
-                    }
-                }
-                this.Dirty = false;
+                await this.buffer.SaveAsync(fs, tokenSource);
             }
             finally
             {
-                this.buffer.UnLock();
+                this.Dirty = false;
             }
         }
 
index 0fdc448..57aaacd 100644 (file)
@@ -41,6 +41,7 @@ namespace FooEditEngine
         GapBuffer<char> buf = new GapBuffer<char>();
         const int MaxSemaphoreCount = 1;
         SemaphoreSlim Semaphore = new SemaphoreSlim(MaxSemaphoreCount);
+        ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim();
 
         public StringBuffer()
         {
@@ -58,31 +59,6 @@ namespace FooEditEngine
             }
         }
 
-        /// <summary>
-        /// ロックを解除します
-        /// </summary>
-        public void UnLock()
-        {
-            this.Semaphore.Release();
-        }
-
-        /// <summary>
-        /// ロックします
-        /// </summary>
-        public void Lock()
-        {
-            this.Semaphore.Wait();
-        }
-
-        /// <summary>
-        /// ロックします
-        /// </summary>
-        /// <returns>Taskオブジェクト</returns>
-        public Task LockAsync()
-        {
-            return this.Semaphore.WaitAsync();
-        }
-
         public StringBuffer(StringBuffer buffer)
             : this()
         {
@@ -101,14 +77,14 @@ namespace FooEditEngine
 
         public string ToString(int index, int length)
         {
-            this.Lock();
+            this.rwlock.EnterReadLock();
 
             StringBuilder temp = new StringBuilder();
             temp.Clear();
             for (int i = index; i < index + length; i++)
                 temp.Append(buf[i]);
 
-            this.UnLock();
+            this.rwlock.ExitReadLock();
 
             return temp.ToString();
         }
@@ -170,19 +146,19 @@ namespace FooEditEngine
 
         internal void Replace(GapBuffer<char> buf)
         {
-            this.Lock();
+            this.rwlock.EnterWriteLock();
 
             this.Clear();
             this.buf = buf;
 
-            this.UnLock();
+            this.rwlock.ExitWriteLock();
 
             this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, 0, 0, buf.Count));
         }
 
         internal void Replace(int index, int length, IEnumerable<char> chars,int count)
         {
-            this.Lock();
+            this.rwlock.EnterWriteLock();
 
             try{
                 if (length > 0)
@@ -191,7 +167,7 @@ namespace FooEditEngine
             }
             finally
             {
-                this.UnLock();
+                this.rwlock.ExitWriteLock();
             }
 
             this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, index, length, count));
@@ -212,11 +188,11 @@ namespace FooEditEngine
                 //内部形式に変換する
                 var internal_str = from s in str where s != '\r' && s != '\0' select s;
 
-                await this.LockAsync().ConfigureAwait(false);
+                this.rwlock.EnterWriteLock();
                 //str.lengthは事前に確保しておくために使用するので影響はない
                 this.buf.InsertRange(index, internal_str, str.Length);
 
-                this.UnLock();
+                this.rwlock.ExitWriteLock();
 
                 if (tokenSource != null)
                     tokenSource.Token.ThrowIfCancellationRequested();
@@ -228,6 +204,36 @@ namespace FooEditEngine
             } while (readCount > 0);
         }
 
+        internal async Task SaveAsync(TextWriter fs,CancellationTokenSource tokenSource=null)
+        {
+            try
+            {
+                this.rwlock.EnterWriteLock();
+                StringBuilder line = new StringBuilder();
+                for (int i = 0; i < this.Length; i++)
+                {
+                    char c = this[i];
+                    line.Append(c);
+                    if (c == Document.NewLine || i == this.Length - 1)
+                    {
+                        string str = line.ToString();
+                        str = str.Replace(Document.NewLine.ToString(), fs.NewLine);
+                        await fs.WriteAsync(str).ConfigureAwait(false);
+                        line.Clear();
+                        if (tokenSource != null)
+                            tokenSource.Token.ThrowIfCancellationRequested();
+#if TEST_ASYNC
+                        System.Threading.Thread.Sleep(10);
+#endif
+                    }
+                }
+            }
+            finally
+            {
+                this.rwlock.ExitWriteLock();
+            }
+        }
+
         internal void ReplaceRegexAll(LineToIndexTable layoutlines, Regex regex, string pattern, bool groupReplace)
         {
             for (int i = 0; i < layoutlines.Count; i++)
@@ -241,7 +247,7 @@ namespace FooEditEngine
                         return pattern;
                 });
 
-                this.Lock();
+                this.rwlock.EnterWriteLock();
                 try
                 {
                     //空行は削除する必要はない
@@ -251,7 +257,7 @@ namespace FooEditEngine
                 }
                 finally
                 {
-                    this.UnLock();
+                    this.rwlock.ExitWriteLock();
                 }
 
                 this.Update(this, new DocumentUpdateEventArgs(UpdateType.Replace, lineHeadIndex, lineLength, output.Length, i));
@@ -269,7 +275,7 @@ namespace FooEditEngine
                 int newLineLength = lineLength;
                 while ((right = ts.IndexOf(this.buf, left, lineHeadIndex + newLineLength)) != -1)
                 {
-                    this.Lock();
+                    this.rwlock.EnterWriteLock();
                     try
                     {
                         this.buf.RemoveRange(right, target.Length);
@@ -277,7 +283,7 @@ namespace FooEditEngine
                     }
                     finally
                     {
-                        this.UnLock();
+                        this.rwlock.ExitWriteLock();
 
                     }
                     left = right + pattern.Length;
@@ -291,12 +297,12 @@ namespace FooEditEngine
 
         internal int IndexOf(string target, int start,bool ci = false)
         {
-            this.Lock();
+            this.rwlock.EnterReadLock();
 
             TextSearch ts = new TextSearch(target,ci);
             int patternIndex = ts.IndexOf(this.buf, start,this.buf.Count);
 
-            this.UnLock();
+            this.rwlock.ExitReadLock();
 
             return patternIndex;
         }