UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PlatformFileCommon.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "Misc/ScopeLock.h"
10#include "Misc/ScopeLock.h"
12#include "HAL/PlatformProcess.h"
13
14#define MANAGE_FILE_HANDLES (#) // this is not longer used, this will error on any attempt to use it
15
17{
18private:
19 friend class FFileHandleRegistry;
20
21 FRegisteredFileHandle* NextLink = nullptr;
22 FRegisteredFileHandle* PreviousLink = nullptr;
23 uint32 ReadRequestCount = 0;
24 bool bIsOpenAndAvailableForClosing = false;
25};
26
27
29{
30public:
34
35 virtual ~FFileHandleRegistry() = default;
36
38 {
39 if (HandlesCurrentlyInUse.Increment() > MaxOpenHandles)
40 {
41 FreeHandles();
42 }
43
45 if (Handle != nullptr)
46 {
47 FScopeLock Lock(&LockSection);
48 LinkToTail(Handle);
49 }
50 else
51 {
52 HandlesCurrentlyInUse.Decrement();
53 }
54
55 return Handle;
56 }
57
59 {
60 bool bWasOpen = false;
61 {
62 FScopeLock Lock(&LockSection);
63 check(Handle->ReadRequestCount == 0);
64 if (Handle->bIsOpenAndAvailableForClosing)
65 {
66 UnLink(Handle);
67 bWasOpen = true;
68 }
69 }
70 if (bWasOpen)
71 {
73 HandlesCurrentlyInUse.Decrement();
74 }
75 }
76
77 // Only returns false if the platform handle cannot be reopened.
78 // TrackEndRead should only be called if TrackStartRead succeeded
80 {
81 {
82 FScopeLock Lock(&LockSection);
83
84 if (Handle->ReadRequestCount++ != 0)
85 {
86 return true;
87 }
88
89 if (Handle->bIsOpenAndAvailableForClosing)
90 {
91 UnLink(Handle);
92 return true;
93 }
94 }
95
96 if (HandlesCurrentlyInUse.Increment() > MaxOpenHandles)
97 {
98 FreeHandles();
99 }
100
101 // can do this out of the lock, in case it's slow
103
104 if (!bSuccess)
105 {
106 FScopeLock Lock(&LockSection);
107 --Handle->ReadRequestCount;
108 }
109
110 return bSuccess;
111 }
112
113 // TrackEndRead should only be called if TrackStartRead succeeded
115 {
116 FScopeLock Lock(&LockSection);
117
118 if (--Handle->ReadRequestCount == 0)
119 {
120 LinkToTail(Handle);
121 }
122 }
123
124protected:
128
129private:
130
131 void FreeHandles()
132 {
133 // do we need to make room for a file handle?
134 while (HandlesCurrentlyInUse.GetValue() > MaxOpenHandles)
135 {
137 {
138 FScopeLock Lock(&LockSection);
139 ToBeClosed = PopFromHead();
140 }
141 if (ToBeClosed)
142 {
143 // close it, freeing up space for new file to open
145 HandlesCurrentlyInUse.Decrement();
146 }
147 else
148 {
149 FPlatformMisc::LowLevelOutputDebugString(TEXT("FFileHandleRegistry: Spinning because we are actively reading from more file handles than we have possible handles.\r\n"));
150 FPlatformProcess::SleepNoStats(.1f);
151 }
152 }
153 }
154
155 void LinkToTail(FRegisteredFileHandle* Handle)
156 {
157 check(!Handle->PreviousLink && !Handle->NextLink && !Handle->bIsOpenAndAvailableForClosing);
158 Handle->bIsOpenAndAvailableForClosing = true;
159 if (OpenAndAvailableForClosingTail)
160 {
161 Handle->PreviousLink = OpenAndAvailableForClosingTail;
162 check(!OpenAndAvailableForClosingTail->NextLink);
163 OpenAndAvailableForClosingTail->NextLink = Handle;
164 }
165 else
166 {
167 check(!OpenAndAvailableForClosingHead);
168 OpenAndAvailableForClosingHead = Handle;
169 }
170 OpenAndAvailableForClosingTail = Handle;
171 }
172
173 void UnLink(FRegisteredFileHandle* Handle)
174 {
175 if (OpenAndAvailableForClosingHead == Handle)
176 {
177 verify(PopFromHead() == Handle);
178 return;
179 }
180 check(Handle->bIsOpenAndAvailableForClosing);
181 Handle->bIsOpenAndAvailableForClosing = false;
182 if (OpenAndAvailableForClosingTail == Handle)
183 {
184 check(OpenAndAvailableForClosingHead && OpenAndAvailableForClosingHead != Handle && Handle->PreviousLink);
185 OpenAndAvailableForClosingTail = Handle->PreviousLink;
186 OpenAndAvailableForClosingTail->NextLink = nullptr;
187 Handle->NextLink = nullptr;
188 Handle->PreviousLink = nullptr;
189 return;
190 }
191 check(Handle->NextLink && Handle->PreviousLink);
192 Handle->NextLink->PreviousLink = Handle->PreviousLink;
193 Handle->PreviousLink->NextLink = Handle->NextLink;
194 Handle->NextLink = nullptr;
195 Handle->PreviousLink = nullptr;
196
197 }
198
199 FRegisteredFileHandle* PopFromHead()
200 {
201 FRegisteredFileHandle* Result = OpenAndAvailableForClosingHead;
202 if (Result)
203 {
204 check(!Result->PreviousLink);
205 check(Result->bIsOpenAndAvailableForClosing);
206 Result->bIsOpenAndAvailableForClosing = false;
207 OpenAndAvailableForClosingHead = Result->NextLink;
208 if (!OpenAndAvailableForClosingHead)
209 {
210 check(OpenAndAvailableForClosingTail == Result);
211 OpenAndAvailableForClosingTail = nullptr;
212 }
213 else
214 {
215 check(OpenAndAvailableForClosingHead->PreviousLink == Result);
216 OpenAndAvailableForClosingHead->PreviousLink = nullptr;
217 }
218 Result->NextLink = nullptr;
219 Result->PreviousLink = nullptr;
220 }
221 return Result;
222 }
223
224 // critical section to protect the below arrays
225 FCriticalSection LockSection;
226
227 int32 MaxOpenHandles = 0;
228
229 FRegisteredFileHandle* OpenAndAvailableForClosingHead = nullptr;
230 FRegisteredFileHandle* OpenAndAvailableForClosingTail = nullptr;
231
232 FThreadSafeCounter HandlesCurrentlyInUse;
233};
234
236{
237public:
239 : FileRegistry(InFileRegistry)
241 {
242 if (bTrackRead)
243 {
244 State = FileRegistry.TrackStartRead(&Handle) ? ETrackingState::Success
245 : ETrackingState::Failure;
246 }
247 else
248 {
249 State = ETrackingState::Skip;
250 }
251 }
252
254 {
255 if (State == ETrackingState::Success)
256 {
257 FileRegistry.TrackEndRead(&Handle);
258 }
259 }
260
261 bool IsValid() const
262 {
263 return State != ETrackingState::Failure;
264 }
265
266private:
267 FFileHandleRegistry& FileRegistry;
269
270 enum class ETrackingState : uint8
271 {
272 Failure,
273 Skip,
274 Success
275 } State;
276};
#define check(expr)
Definition AssertionMacros.h:314
#define verify(expr)
Definition AssertionMacros.h:319
bool bSuccess
Definition ConvexDecomposition3.cpp:819
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
FRWLock Lock
Definition UnversionedPropertySerialization.cpp:921
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition PlatformFileCommon.h:236
bool IsValid() const
Definition PlatformFileCommon.h:261
FFileHandleRegistryReadTracker(FFileHandleRegistry &InFileRegistry, FRegisteredFileHandle &InHandle, bool bTrackRead=true)
Definition PlatformFileCommon.h:238
~FFileHandleRegistryReadTracker()
Definition PlatformFileCommon.h:253
Definition PlatformFileCommon.h:29
virtual void PlatformCloseFile(FRegisteredFileHandle *)=0
virtual bool PlatformReopenFile(FRegisteredFileHandle *)=0
FRegisteredFileHandle * InitialOpenFile(const TCHAR *Filename)
Definition PlatformFileCommon.h:37
FFileHandleRegistry(int32 InMaxOpenHandles)
Definition PlatformFileCommon.h:31
virtual ~FFileHandleRegistry()=default
void UnTrackAndCloseFile(FRegisteredFileHandle *Handle)
Definition PlatformFileCommon.h:58
virtual FRegisteredFileHandle * PlatformInitialOpenFile(const TCHAR *Filename)=0
bool TrackStartRead(FRegisteredFileHandle *Handle)
Definition PlatformFileCommon.h:79
void TrackEndRead(FRegisteredFileHandle *Handle)
Definition PlatformFileCommon.h:114
Definition PlatformFileCommon.h:17
Definition ScopeLock.h:141
Definition ThreadSafeCounter.h:14
int32 Increment()
Definition ThreadSafeCounter.h:52
int32 Decrement()
Definition ThreadSafeCounter.h:75
int32 GetValue() const
Definition ThreadSafeCounter.h:120
Definition GenericPlatformFile.h:117
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
static CORE_API void LowLevelOutputDebugString(const TCHAR *Message)
Definition GenericPlatformMisc.cpp:935