디시인사이드 갤러리

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

갤러리 본문 영역

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

ㅆㅇㅆ(124.216) 2025.03.09 15:42:25
조회 44 추천 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 - -
2827477 나님 스벅 신메뉴 음미 중? 딱님갤로그로 이동합니다. 03.09 18 0
2827475 쭈쭈맘마❤+ ♥냥덩♥갤로그로 이동합니다. 03.09 30 0
2827471 나님 저메추좀요???? 딱님갤로그로 이동합니다. 03.09 14 0
2827469 나님 오운완 [2] 딱님갤로그로 이동합니다. 03.09 31 0
2827465 젠머신 싼 미니 컴퓨터가 있다고 한다 발명도둑잡기갤로그로 이동합니다. 03.09 20 0
2827463 비주얼 스튜디오에서 이전에 작업할 소스파일 어떻게 불러오나요? 프갤러(112.157) 03.09 16 0
2827462 뭐하고 살아야하나 [2] 프갤러(39.7) 03.09 47 0
2827461 넷마블 게임박물관 발명도둑잡기갤로그로 이동합니다. 03.09 104 0
2827459 나는 나중에 트럼프와 머스크가 싸울 것으로 예상한다 발명도둑잡기갤로그로 이동합니다. 03.09 25 0
2827457 힝힝 아이디 하나 잃어버렸다..ㅇㅅㅇㅇ [1] 헤르 미온느갤로그로 이동합니다. 03.09 29 0
2827455 [기억할 오늘] 국가가 보장해야 할 개인의 자유의 범위 발명도둑잡기갤로그로 이동합니다. 03.09 16 0
2827454 정치판이 또 시끄럽나보구나 [2] hrin(118.235) 03.09 30 0
2827453 심지어 멀티쓰레딩은 저렇게 대놓고 나오는 에러는 고마운편임 프갤러(211.210) 03.09 31 2
2827450 흠... 전공공부 어떻게 하는거냐... 이 벽돌을 어떻게 해석해야함... [1] ㅇㅇ(123.213) 03.09 21 0
2827449 ❤✨☀⭐나님 시작합니당⭐☀✨❤ ♥냥덩♥갤로그로 이동합니다. 03.09 17 0
2827447 ‘연방’과 ‘연맹’으로 쪼개진 미국, 그 운명은 발명도둑잡기갤로그로 이동합니다. 03.09 18 0
2827445 지잡 컴공 졸업하면 연봉 2600 받고싶은데 취업시장 진짜 많이 힘드냐? [3] ㅇㅇ(223.38) 03.09 60 0
2827444 ㅆㅇㅆ코드 지피티한테 복붙하니까 aaa게임용 코드라고하노 [2] ㅇㅇ(112.163) 03.09 49 0
2827441 실행하고 끄고 실행하고 끄고 실행하고 끄고 정신병 걸리겠다 ㅆㅇㅆ(124.216) 03.09 20 0
아마, 내 생각엔 풀링 하는 과정에서 문제가 있었던듯 하다. [5] ㅆㅇㅆ(124.216) 03.09 44 0
2827438 전세계가 미국빼고 폭망중인데 [2] 슈퍼막코더(126.194) 03.09 35 0
2827436 화교분탕들의 집요한 메건 연애설 날조 - 현무아재 ㅇㅇ(110.70) 03.09 24 0
2827434 안철수는 인터넷도 없는데 어떻게 공부했냐? [6] 수크라제갤로그로 이동합니다. 03.09 69 1
2827433 쓰레드 스위칭하면서 문제가 발생한건가 [3] ㅆㅇㅆ(124.216) 03.09 41 0
2827429 값은 나옴. 값은 나오는데 에러코드가 나옴 [2] ㅆㅇㅆ(124.216) 03.09 29 0
2827427 비동기가 좆같은게 에러가 낫는데 추적이 어려움 [9] ㅆㅇㅆ(124.216) 03.09 52 0
2827425 한국은 사회주의 국가가 되는게 딱이다. [4] 프갤러(223.63) 03.09 35 0
2827424 ‘尹 석방’ 놓고…검찰 1인자 vs 2인자 충돌? 발명도둑잡기갤로그로 이동합니다. 03.09 26 0
2827423 “월급 100만원 미만 손님 안받아”…논란 일자 “오해” 발뺌 발명도둑잡기갤로그로 이동합니다. 03.09 20 0
2827422 韓 ‘경제 근간’ 제조업이 흔들린다 발명도둑잡기갤로그로 이동합니다. 03.09 16 0
2827420 보통 사람은 타인을 판단할때 자기 지식 범위내에서 판단하는데 [1] ㅆㅇㅆ(124.216) 03.09 47 0
2827419 이혜정 "의사 월급 얼마 안되는데 카드값 800만원…자녀들 빚 걱정" 발명도둑잡기갤로그로 이동합니다. 03.09 19 0
2827417 오세훈 “지하철 요금 3월 인상 계획” 발명도둑잡기갤로그로 이동합니다. 03.09 30 0
2827416 골드바 불티나더니 바빠진 을지로 금고 상인들[르포] 발명도둑잡기갤로그로 이동합니다. 03.09 27 0
2827415 우리 회사 개발자님 카톡 상메 상태.. 익명의따당이갤로그로 이동합니다. 03.09 47 0
2827413 “남녀 벌거벗고 함께 씻어도 문제없다” 기록된 시대...목욕의 역사 발명도둑잡기갤로그로 이동합니다. 03.09 22 0
2827412 매크로 때문에 그래픽카드를 살 수가 없다 시발 프갤러(121.188) 03.09 22 0
2827410 이삭토스트 말고 이삭러스트는 없냐? [1] 프갤러(223.57) 03.09 28 0
2827409 "팬티 내려" 얼굴 갖다댄 선임, 군함서 장소 안가리고 강제추행 발명도둑잡기갤로그로 이동합니다. 03.09 18 0
2827408 컴공 2학년 무슨 공부를 해야할까요.. 인생고민 [1] ㅇㅇ갤로그로 이동합니다. 03.09 38 0
2827406 전 세계가 주목한 윤석열 대통령 석방 장면 ♥냥덩♥갤로그로 이동합니다. 03.09 26 1
2827402 ㅆㅇㅆ 보니까 전에 본 동기부여 영상 생각남 [4] 프갤러(223.38) 03.09 49 0
2827399 언리얼에 C++, 블루프린트 말고도 도입될 Verse 언어 발명도둑잡기갤로그로 이동합니다. 03.09 26 0
2827397 영국인 모델: 안전하게 집에 혼자 갈 수 있는 게 너무 편해요 발명도둑잡기갤로그로 이동합니다. 03.09 22 0
2827396 화교분탕들의 집요한 메건 연애썰 날조 - 탈덕수용소 ㅇㅇ(110.70) 03.09 23 0
2827394 내가 느끼는게 웹은 기본적으로 오픈소스가 활발한데 게임은 [2] ㅆㅇㅆ(124.216) 03.09 37 0
2827393 웹 개발 아키텍쳐나 이런건 유명 개발자 블로그가 있는데 ㅆㅇㅆ(124.216) 03.09 33 0
2827392 휴대용 게임기 버추얼 박물관 발명도둑잡기갤로그로 이동합니다. 03.09 16 0
2827391 이거 누구 저격인가요? [3] 프갤러(223.38) 03.09 44 0
2827390 퍼블 프론트 공부하시는분 계신가요? 프갤러(180.83) 03.09 27 0
뉴스 [드림하이] ‘눈물의 여왕 신드롬’ 김수현, 홍이삭과 함께 ‘Dreaming’ 음원 발매! 감동 예고! 디시트렌드 03.09
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2