Skip to content

Commit 369297e

Browse files
committed
perf: IMemoryOwner 소유권 관리 안전성 개선
- ChatSegment의 WithAudioMemory 메서드 상태 정리 로직 추가 - AttachAudioMemory 메서드로 불변 인스턴스 생성 지원 - TextToSpeechResponse에 TryTakeAudioOwner 메서드 추가 - 메모리 누수 및 이중 해제 방지 메커니즘 강화 - 코드 가독성을 위한 주석 간소화
1 parent 0eaa3d8 commit 369297e

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

ProjectVG.Application/Models/Chat/ChatSegment.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public ChatSegment WithAudioData(byte[] audioData, string audioContentType, floa
8585
};
8686
}
8787

88-
// 소유권 이전: 호출자는 audioMemoryOwner를 해제하지 말 것
88+
// 주의: 원본 인스턴스의 AudioMemoryOwner 해제됨
8989
public ChatSegment WithAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audioDataSize, string audioContentType, float audioLength)
9090
{
9191
if (audioMemoryOwner is null)
@@ -97,8 +97,38 @@ public ChatSegment WithAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audi
9797
audioDataSize,
9898
$"audioDataSize는 0 이상 {audioMemoryOwner.Memory.Length} 이하여야 합니다.");
9999

100-
// 기존 소유자 해제
100+
// 기존 소유자 해제 및 상태 정리
101101
this.AudioMemoryOwner?.Dispose();
102+
this.AudioMemoryOwner = null;
103+
this.AudioDataSize = 0;
104+
105+
return new ChatSegment
106+
{
107+
Content = this.Content,
108+
Order = this.Order,
109+
Emotion = this.Emotion,
110+
Actions = this.Actions,
111+
AudioMemoryOwner = audioMemoryOwner,
112+
AudioDataSize = audioDataSize,
113+
AudioContentType = audioContentType,
114+
AudioLength = audioLength,
115+
AudioData = null
116+
};
117+
}
118+
119+
/// <summary>
120+
/// 오디오 메모리를 부착한 새 인스턴스 생성 (원본 불변)
121+
/// </summary>
122+
public ChatSegment AttachAudioMemory(IMemoryOwner<byte> audioMemoryOwner, int audioDataSize, string audioContentType, float audioLength)
123+
{
124+
if (audioMemoryOwner is null)
125+
throw new ArgumentNullException(nameof(audioMemoryOwner));
126+
127+
if (audioDataSize < 0 || audioDataSize > audioMemoryOwner.Memory.Length)
128+
throw new ArgumentOutOfRangeException(
129+
nameof(audioDataSize),
130+
audioDataSize,
131+
$"audioDataSize는 0 이상 {audioMemoryOwner.Memory.Length} 이하여야 합니다.");
102132

103133
return new ChatSegment
104134
{

ProjectVG.Infrastructure/Integrations/TextToSpeechClient/Models/TextToSpeechResponse.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace ProjectVG.Infrastructure.Integrations.TextToSpeechClient.Models
55
{
6+
/// <summary>
7+
/// TTS API 응답 모델 - IMemoryOwner 기반 메모리 관리
8+
/// </summary>
69
public class TextToSpeechResponse
710
{
811
/// <summary>
@@ -25,6 +28,7 @@ public class TextToSpeechResponse
2528

2629
/// <summary>
2730
/// ArrayPool 기반 오디오 메모리 소유자 (LOH 방지)
31+
/// 주의: ChatSegment로 이전하지 않을 경우 직접 Dispose() 필요
2832
/// </summary>
2933
[JsonIgnore]
3034
public IMemoryOwner<byte>? AudioMemoryOwner { get; set; }
@@ -52,5 +56,20 @@ public class TextToSpeechResponse
5256
/// </summary>
5357
[JsonIgnore]
5458
public int StatusCode { get; set; } = 200;
59+
60+
/// <summary>
61+
/// 오디오 메모리 소유권을 안전하게 가져갑니다
62+
/// </summary>
63+
public bool TryTakeAudioOwner(out IMemoryOwner<byte>? owner, out int size)
64+
{
65+
owner = AudioMemoryOwner;
66+
size = AudioDataSize;
67+
68+
// 소유권 이전 후 현재 객체에서 제거하여 중복 해제 방지
69+
AudioMemoryOwner = null;
70+
AudioDataSize = 0;
71+
72+
return owner != null;
73+
}
5574
}
5675
}

0 commit comments

Comments
 (0)