Files
FlaxEngine/Source/Engine/Content/Storage/FlaxChunk.h
Wojtek Figat d84cef0c18 Fix crash due to async content data streaming
Properly checks for asset data unloading before taking lock on asset chunks.
#3358 #3085 #3515
2025-11-09 22:15:41 +01:00

191 lines
4.1 KiB
C++

// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/DataContainer.h"
#include "../Config.h"
/// <summary>
/// Custom flags for the storage chunk data.
/// </summary>
enum class FlaxChunkFlags
{
/// <summary>
/// Nothing.
/// </summary>
None = 0,
/// <summary>
/// Compress chunk data using LZ4 algorithm.
/// </summary>
CompressedLZ4 = 1,
/// <summary>
/// Prevents chunk file data from being unloaded if unused for a certain amount of time. Runtime-only flag, not saved with the asset.
/// </summary>
KeepInMemory = 2,
};
DECLARE_ENUM_OPERATORS(FlaxChunkFlags);
/// <summary>
/// Represents chunks of data used by the content storage layer
/// </summary>
class FLAXENGINE_API FlaxChunk
{
public:
/// <summary>
/// Chunk of data location info
/// </summary>
struct Location
{
/// <summary>
/// Address of the chunk beginning in file
/// </summary>
uint32 Address;
/// <summary>
/// Chunk size (in bytes)
/// Note: chunk which size equals 0 is considered as not existing
/// </summary>
uint32 Size;
/// <summary>
/// Init
/// </summary>
Location()
: Address(0)
, Size(0)
{
}
/// <summary>
/// Init
/// </summary>
/// <param name="location">The location.</param>
/// <param name="size">The size.</param>
Location(uint32 location, uint32 size)
: Address(location)
, Size(size)
{
}
};
public:
/// <summary>
/// The chunk location in file.
/// </summary>
Location LocationInFile;
/// <summary>
/// The chunk flags.
/// </summary>
FlaxChunkFlags Flags = FlaxChunkFlags::None;
/// <summary>
/// The last usage time.
/// </summary>
double LastAccessTime = 0.0;
/// <summary>
/// Flag set to indicate that chunk is during loading (atomic access to sync multiple reading threads).
/// </summary>
int64 IsLoading = 0;
/// <summary>
/// The chunk data.
/// </summary>
BytesContainer Data;
public:
/// <summary>
/// Initializes a new instance of the <see cref="FlaxChunk"/> class.
/// </summary>
FlaxChunk()
{
}
/// <summary>
/// Finalizes an instance of the <see cref="FlaxChunk"/> class.
/// </summary>
~FlaxChunk()
{
}
public:
/// <summary>
/// Gets this chunk data pointer.
/// </summary>
FORCE_INLINE byte* Get()
{
return Data.Get();
}
/// <summary>
/// Gets this chunk data pointer.
/// </summary>
FORCE_INLINE const byte* Get() const
{
return Data.Get();
}
/// <summary>
/// Gets this chunk data pointer.
/// </summary>
template<typename T>
FORCE_INLINE T* Get() const
{
return (T*)Data.Get();
}
/// <summary>
/// Gets this chunk data size (in bytes).
/// </summary>
FORCE_INLINE int32 Size() const
{
return Data.Length();
}
/// <summary>
/// Determines whether this chunk is loaded.
/// </summary>
FORCE_INLINE bool IsLoaded() const
{
return Data.IsValid() && Platform::AtomicRead(&IsLoading) == 0;
}
/// <summary>
/// Determines whether this chunk is missing (no data loaded or assigned).
/// </summary>
FORCE_INLINE bool IsMissing() const
{
return !IsLoaded();
}
/// <summary>
/// Determines whether this chunk exists in a file.
/// </summary>
FORCE_INLINE bool ExistsInFile() const
{
return LocationInFile.Size > 0;
}
/// <summary>
/// Registers the usage operation of chunk data.
/// </summary>
void RegisterUsage();
/// <summary>
/// Unloads this chunk data.
/// </summary>
void Unload()
{
Data.Release();
}
/// <summary>
/// Clones this chunk data (doesn't copy location in file).
/// </summary>
/// <returns>The cloned chunk.</returns>
FlaxChunk* Clone() const;
};