디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

아마, 내 생각엔 풀링 하는 과정에서 문제가 있었던듯 하다.

ㅆㅇㅆ(124.216) 2025.03.09 15:42:25
조회 50 추천 0 댓글 5

using System;

using System.Runtime.CompilerServices;

using UnityEngine;


namespace JDWTaskSystem

{

    /// <summary>

    /// 연속 작업 실행 래퍼 (박싱 방지) – 풀링을 위해 제공

    /// 외부에는 읽기 전용 인터페이스를 제공하며, 내부에서는 풀 재사용을 위해 상태를 재설정할 수 있도록 제공

    /// </summary>

    public sealed class ContinuationBox : ITaskCompletionAction

    {

        private Action continuation; // 실행할 연속 작업

        private DateTime lastUsed;   // 마지막 사용 시각

        private int usageCount;      // 사용 횟수 추적

        private const int UsageThreshold = 100; // 사용 횟수 임계값

        private static readonly Action emptyAction = () => { }; // 기본 빈 액션 (NullReference 방지)


        /// <summary>

        /// 등록된 연속 작업(continuation)을 반환

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public Action GetContinuation()

        {

            return continuation;

        }


        /// <summary>

        /// 마지막 사용 시각 (UTC)을 반환

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public DateTime GetLastUsed()

        {

            return lastUsed;

        }


        /// <summary>

        /// 내부용 세터: continuation을 설정

        /// </summary>

        /// <param name="value">설정할 액션</param>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        internal void SetContinuation(Action value)

        {

            if (value == null)

            {

                throw new ArgumentNullException(nameof(value));

            }

            continuation = value;

        }


        /// <summary>

        /// 내부용 세터: 마지막 사용 시각을 설정

        /// </summary>

        /// <param name="value">설정할 시각</param>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        internal void SetLastUsed(DateTime value)

        {

            lastUsed = value;

        }


        /// <summary>

        /// 파라미터 없는 생성자 – 풀에서 인수 없이 생성될 때 사용되며, 이후 Reinitialize로 상태를 설정

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public ContinuationBox()

        {

            continuation = emptyAction; // 기본적으로 빈 액션으로 초기화

            lastUsed = DateTime.UtcNow; // 현재 시각으로 설정

            usageCount = 0;             // 사용 횟수 초기화

        }


        /// <summary>

        /// 생성자 – 지정된 연속 작업을 설정하고, 마지막 사용 시각을 현재로 초기화

        /// </summary>

        /// <param name="continuation">실행할 액션</param>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public ContinuationBox(Action continuation)

        {

            SetContinuation(continuation); // 주어진 액션 설정

            lastUsed = DateTime.UtcNow;    // 현재 시각으로 설정

            usageCount = 0;                // 사용 횟수 초기화

        }


        /// <summary>

        /// 내부용 재초기화 메서드 – 풀에서 재사용할 때 새로운 연속 작업과 함께 사용 횟수를 추적하여, 일정 횟수 이상 사용된 경우에만 마지막 사용 시각을 갱신

        /// </summary>

        /// <param name="continuation">새로운 액션</param>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        internal void Reinitialize(Action continuation)

        {

            SetContinuation(continuation); // 새로운 액션 설정

            usageCount++;                  // 사용 횟수 증가

            if (usageCount >= UsageThreshold) // 임계값 도달 시

            {

                SetLastUsed(DateTime.UtcNow); // 마지막 사용 시각 갱신

                usageCount = 0;               // 사용 횟수 리셋

            }

        }


        /// <summary>

        /// 내부용 Reset 메서드 – 풀에서 반환할 때 상태를 초기화

        /// continuation은 빈 액션(() => {})으로 설정하여 NullReferenceException을 방지

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        internal void Reset()

        {

            continuation = emptyAction;    // 빈 액션으로 리셋

            usageCount = 0;                // 사용 횟수 초기화

            SetLastUsed(DateTime.UtcNow);  // 마지막 사용 시각 갱신

        }


        /// <summary>

        /// ITaskCompletionAction 인터페이스 구현 – 등록된 연속 작업을 실행한 후, 자동으로 풀에 반환

        /// </summary>

        /// <param name="source">작업 소스 (필요시 참조용)</param>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public void Invoke(ITaskSource source)

        {

            try

            {

                Action cont = GetContinuation();

                if (cont == null)

                {

                    Debug.LogError("Continuation is null in ContinuationBox!");

                    return;

                }

                cont.Invoke();

            }

            catch (Exception ex)

            {

                Debug.LogError($"Continuation execution failed in ContinuationBox: {ex.Message}\nStackTrace: {ex.StackTrace}");

                throw; // 상위로 전파해 디버깅 용이

            }

            finally

            {

                ContinuationPool.Return(this); // 실행 후 풀에 반환

            }

        }

    }

}

using System;

using System.Collections.Generic;

using System.Runtime.CompilerServices;

using System.Threading;

using UnityEngine;


namespace JDWTaskSystem

{

    /// <summary>

    /// 비동기 작업의 기본 TaskSource 클래스

    /// TaskSource는 비동기 작업의 상태, 결과, 완료 콜백을 관리함.

    /// 풀링 최적화와 할당 최소화를 위해 설계됨.

    /// </summary>

    /// <typeparam name="TResult">비동기 작업 결과 타입</typeparam>

    public abstract class TaskSourceBase<TResult> : ITaskSource<TResult>, ITaskPoolable

    {

        // 버전 관리를 위해 long 사용 (오버플로우 방지)

        protected long version;

        protected TaskStatus currentState;

        protected TResult result;

        protected Exception exception;

        // 완료 콜백을 관리할 List; 이전 작업의 잔재 제거를 위해 OnAcquireFromPool에서 새로 초기화함.

        private List<ITaskCompletionAction> continuations;

        private readonly object continuationsLock = new object();

        private bool isInPool; // 풀 상태 여부


        // 정적 예외 객체 (할당 최소화를 위해)

        private static readonly Exception TaskFailed = new Exception("Task failed");

        private static readonly OperationCanceledException TaskCanceled = new OperationCanceledException();


        #region Core Methods


        /// <summary>

        /// 현재 Task 버전을 반환함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public long GetVersion() => Interlocked.Read(ref version);


        /// <summary>

        /// 풀에서 가져올 때 초기화함.

        /// </summary>

        public virtual void OnAcquireFromPool()

        {

            SetIsInPool(false);

            Interlocked.Increment(ref version);

            Interlocked.MemoryBarrier();

            currentState = TaskStatus.Pending;

            result = default(TResult);

            exception = null;

            // 새 리스트로 초기화하여 이전 콜백 잔재 제거

            continuations = new List<ITaskCompletionAction>();

        }


        /// <summary>

        /// 풀로 돌려줄 때 정리함.

        /// </summary>

        public virtual void OnReleaseToPool()

        {

            SetIsInPool(true);

            result = default(TResult);

            exception = null;

            continuations = null;

        }


        /// <summary>

        /// 풀에 있는지 여부를 반환함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public bool GetIsInPool() => isInPool;


        /// <summary>

        /// 객체의 풀 상태를 설정함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public void SetIsInPool(bool value) => isInPool = value;


        /// <summary>

        /// 현재 Task 상태를 반환함. 토큰이 일치하지 않으면 Faulted로 처리함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public TaskStatus GetStatus(long token)

        {

            return token != Interlocked.Read(ref version) ? TaskStatus.Faulted : currentState;

        }


        /// <summary>

        /// Task 완료 시 실행할 콜백을 등록함.

        /// 토큰이나 상태가 맞지 않으면 즉시 콜백 실행함.

        /// </summary>

        public virtual void OnCompleted(ITaskCompletionAction continuation, long token)

        {

            if (token != Interlocked.Read(ref version) || currentState != TaskStatus.Pending)

            {

                continuation.Invoke(this);

                return;

            }


            lock (continuationsLock)

            {

                // continuations가 null인 경우는 거의 없지만, 안전을 위해 검사

                if (continuations == null)

                {

                    Debug.LogWarning("Continuations list is null in OnCompleted, invoking immediately.");

                    continuation.Invoke(this);

                }

                else

                {

                    continuations.Add(continuation);

                }

            }

        }


        /// <summary>

        /// Task 결과를 반환함.

        /// 상태에 따라 결과를 반환하거나 예외를 던짐.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public TResult GetResult(long token)

        {

            if (token != Interlocked.Read(ref version))

            {

                throw new InvalidOperationException("Invalid task version");

            }


            return currentState switch

            {

                TaskStatus.Succeeded => result,

                TaskStatus.Faulted => throw exception ?? TaskFailed,

                TaskStatus.Canceled => throw TaskCanceled,

                _ => throw new InvalidOperationException("Task not completed")

            };

        }


        /// <summary>

        /// Task를 성공 상태로 전환하고 결과를 저장하며 등록된 콜백을 실행함.

        /// </summary>

        public virtual bool TrySetResult(TResult value)

        {

            lock (this)

            {

                if (currentState != TaskStatus.Pending)

                    return false;

                currentState = TaskStatus.Succeeded;

                result = value;

                ExecuteContinuations();

                return true;

            }

        }


        /// <summary>

        /// Task를 실패 상태로 전환하고 예외를 저장하며 등록된 콜백을 실행함.

        /// </summary>

        public virtual bool TrySetException(Exception ex)

        {

            lock (this)

            {

                if (currentState != TaskStatus.Pending)

                    return false;

                currentState = TaskStatus.Faulted;

                exception = ex ?? TaskFailed;

                ExecuteContinuations();

                return true;

            }

        }


        /// <summary>

        /// Task를 취소 상태로 전환하고 등록된 콜백을 실행함.

        /// </summary>

        protected virtual bool TrySetCanceled(CancellationToken cancellationToken)

        {

            lock (this)

            {

                if (currentState != TaskStatus.Pending)

                    return false;

                currentState = TaskStatus.Canceled;

                exception = new OperationCanceledException(cancellationToken);

                ExecuteContinuations();

                return true;

            }

        }


        /// <summary>

        /// Task 상태를 초기화함. (재사용을 위해)

        /// </summary>

        protected virtual void ResetState()

        {

            currentState = TaskStatus.Pending;

            version = 0;

            result = default(TResult);

            exception = null;

            continuations?.Clear();

        }


        /// <summary>

        /// 등록된 모든 콜백을 실행함.

        /// </summary>

        private void ExecuteContinuations()

        {

            List<ITaskCompletionAction> toExecute = null;

            lock (continuationsLock)

            {

                if (continuations != null && continuations.Count > 0)

                {

                    // 안전한 스냅샷 복사

                    toExecute = new List<ITaskCompletionAction>(continuations);

                    continuations.Clear();

                }

            }


            if (toExecute != null)

            {

                foreach (var callback in toExecute)

                {

                    try

                    {

                        if (callback == null)

                        {

                            Debug.LogWarning("Null callback found in continuations list, skipping.");

                            continue;

                        }

                        ContinuationRunner.RunContinuation(callback);

                    }

                    catch (Exception ex)

                    {

                        Debug.LogError($"Continuation execution failed in TaskSourceBase: {ex.Message}\nStackTrace: {ex.StackTrace}\nCallback Type: {callback?.GetType()}");

                        // 상위로 전파하지 않고 로그만 남김

                    }

                }

            }

        }


        /// <summary>

        /// Task 결과의 유효성을 검사함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public void ValidateResult(long token)

        {

            if (token != Interlocked.Read(ref version))

                throw new InvalidOperationException("Task version mismatch");

        }


        /// <summary>

        /// Task에서 발생한 예외를 반환함.

        /// </summary>

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public Exception TryGetException(long token)

        {

            return token != Interlocked.Read(ref version)

                ? new InvalidOperationException("Task version mismatch")

                : exception;

        }

        #endregion


        #region ITaskSource & ITaskPoolable 구현

        void ITaskSource.Reset(long token) => OnAcquireFromPool();

        void ITaskSource.Cleanup(long token) => OnReleaseToPool();

        long ITaskSource.GetVersion() => GetVersion();

        #endregion

    }

}

ContinuationBox에서 Invoke()에서 예외 던지는거보면

비동기 실행시 콜백(Continuation) 저장하고 실행하는 과정에서


여기서 뭔가 에러가 있는듯한데


모르겄다.


추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
등록순정렬 기준선택
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 매니저들에게 가장 잘할 것 같은 스타는? 운영자 25/03/10 - -
공지 프로그래밍 갤러리 이용 안내 [87] 운영자 20.09.28 42260 64
2827926 si도 요즘 취업힘들다던데 [1] ㅇㅇ갤로그로 이동합니다. 17:00 7 0
2827925 삼성 코테 프갤러(210.107) 16:55 9 0
2827924 고졸 30살인데 일자리 있으면 무조건 ㄱ임?? [16] 프갤러(125.138) 16:50 46 0
2827923 여자얘기만들어도 고통스럽고 힘들다 [2] 프갤러(175.223) 16:48 16 0
2827922 사사로운 디테일 하나 놓치지 않아야 개발귀(鬼) [3] 딱님갤로그로 이동합니다. 16:47 15 0
2827921 아 보1지 빨고 싶다 [3] 아스카영원히사랑해갤로그로 이동합니다. 16:36 43 0
2827920 ㅇㅇ 프갤러(211.234) 16:36 11 0
2827919 브라우저 차별 두는건 첨보네 ㅇㅅㅇ [2] 강유현갤로그로 이동합니다. 16:35 30 0
2827918 1일1잔디 개발블로그 역겹다 프갤러(121.137) 16:35 19 1
2827917 AI 그림이나 봐 프갤러(211.234) 16:30 11 0
2827916 [애니 뉴스] 프로젝트 KV 관련되어 글을 쓰는데- [3] 프갤러(121.172) 16:28 23 0
2827915 ㅇㅇ 프갤러(211.234) 16:21 12 0
2827914 은행이 윈폼을 쓴다니 ㅇㅅㅇ [2] 강유현갤로그로 이동합니다. 16:16 21 0
2827913 지겹구나. 러스트를 쓰지 못하는 삶이란 [1] 프갤러(121.138) 16:14 17 0
2827912 컴공 진로 추천좀 [2] ㅇㅇ갤로그로 이동합니다. 16:12 22 0
2827911 [애니 뉴스] 프로젝트KV와 블루아카이브 추가- [2] 프갤러(121.172) 16:10 17 0
2827910 김밥집 11시오픈은 리얼 선넘은듯 ㅇㅅㅇ [3] ㅇㅇ(223.38) 16:07 24 0
2827909 뭔가 맨날 SI에서 갑질만 당하다가 [2] 강유현갤로그로 이동합니다. 16:05 26 0
2827908 태국 레이디 보이 올리지마 프갤러(211.234) 16:01 23 0
2827906 ㅠㅠ 프갤러(211.234) 15:57 15 0
2827903 일론머스크는 어서 도라에몽로봇 만드셈 프갤러(211.234) 15:54 15 0
2827902 컴퓨터 지식같은건 어디서 배우는거냐 [5] ㅇㅇ갤로그로 이동합니다. 15:53 30 0
2827901 그림 2 프갤러(211.234) 15:49 16 0
2827900 그림그림 프갤러(211.234) 15:43 23 0
2827899 연애도 못해 직업도 사라져 대체 어쩌라는거냐 [1] 프갤러(211.234) 15:41 28 0
2827898 코딩은 이제 사양직업 [3] 프갤러(211.234) 15:36 54 0
2827897 컴맹 스칼라 쓸려고 이클립스 깔았는데 [1] ㅇㅇ갤로그로 이동합니다. 15:36 16 0
2827896 삼성 정직원이랑 삼성으로 파견 간 직원 차이 프갤러(121.134) 15:30 31 0
2827895 개발귀(鬼)의 경지에 다다르면 내비치는 세계가 보이게 돼 버려~ 딱님갤로그로 이동합니다. 15:28 21 0
2827894 다이어트 해야되는데 발명도둑잡기갤로그로 이동합니다. 15:27 15 0
2827893 휴대폰 소니 액정이 깨져서 상심이 크다. 넥도리아(222.233) 15:26 11 0
2827892 fc2에서 질싸받는 여고생들 사연을 들어보고싶다.. [1] ㅇㅇ(39.7) 15:17 42 0
2827891 회사 다니면서 프리뛰면 소득잡혀서 들키나 ㅇㅅㅇ? [3] 강유현갤로그로 이동합니다. 15:16 28 0
2827890 연대컴공졸업(서울캠) 졸업후 5년 공백기 무경력 국비면접보러 가는중 [3] 프갤러(223.38) 15:14 60 0
2827889 비전공자 국비 부트캠프 어떤게 낫나요? 프갤러(59.12) 15:10 22 0
2827888 웹사이트 크롤링 불법 질문 [1] 프갤러(122.40) 15:10 18 0
2827887 nimf 소스코드는 몇 줄이나 될까.. ㅎㅎ [2] *루비*갤로그로 이동합니다. 15:07 27 1
2827885 너흰 API 라이브러리 프레임워크 플러그인 이런 용어 차이 앎? [9] 프갤러(221.146) 14:59 49 0
2827884 일부 파일을 cpp로 변경 한 후 컴파일한 결과 *루비*갤로그로 이동합니다. 14:58 16 0
2827883 나는야 조증이 너무나 좋아 재현갤로그로 이동합니다. 14:53 15 0
2827882 LLM API이용해서 코딩만들면 어느정도 자동화돼??? [5] 프갤러(117.110) 14:52 44 0
2827881 아이돌학교와 프듀 주작 끌올의 전후관계 ㅇㅇ(175.223) 14:50 21 0
2827880 [자유 대한민국] 수천조원에 달하는 피해보상금액- 프갤러(121.172) 14:49 18 0
2827878 아웃소싱이야말로 인류최고의 발명품 프갤러(218.158) 14:48 16 0
2827876 와.. 이게 뭐하는 개짓거리냐 !! [2] *루비*갤로그로 이동합니다. 14:47 29 0
2827875 한국은 데이터아웃소싱 기업은 없음? [3] 프갤러(218.158) 14:39 27 0
2827874 MSSQL은 병원이나 공장에서 잘 쓰이나 ㅇㅅㅇ 강유현갤로그로 이동합니다. 14:38 21 0
2827873 지방 신도시 특징 ㅇㅇ(119.56) 14:33 14 0
2827872 통계에 R이나 파이썬 쓰는건 낭비다 이기야 [6] 슈퍼막코더(126.255) 14:31 39 0
뉴스 ‘폭싹 속았수다’ 1막 ‘봄’ (1-4화) 가득 채운 아이유의 존재감, ‘애순’ 그 자체였다 디시트렌드 10:00
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2