Documentation

Multithreading

ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ позволяСт максимально ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ возмоТности соврСмСнных многоядСрных процСссоров, Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ²Ρ‹ΡˆΠ°Ρ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΈΠ³Ρ€.

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ

Π‘ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈΠ³Ρ€Ρ‹ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ эффСктивного использования всСх доступных рСсурсов процСссора. Wudgine прСдоставляСт ΠΌΠΎΡ‰Π½ΡƒΡŽ систСму многопоточности, которая позволяСт Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ²Π°Ρ‚ΡŒ вычислСния ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΈΠ³Ρ€Ρ‹.

БистСма Π·Π°Π΄Π°Π½ΠΈΠΉ (Job System)

БистСма Π·Π°Π΄Π°Π½ΠΈΠΉ Wudgine β€” это высокоуровнСвый интСрфСйс для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π»Π΅Π³ΠΊΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ²Π°Ρ‚ΡŒ вычислСния.

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ

  • Π—Π°Π΄Π°Π½ΠΈΠ΅ (Job) β€” атомарная Π΅Π΄ΠΈΠ½ΠΈΡ†Π° Ρ€Π°Π±ΠΎΡ‚Ρ‹, которая ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ
  • ΠŸΡƒΠ» ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² (Thread Pool) β€” Π½Π°Π±ΠΎΡ€ Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² для выполнСния Π·Π°Π΄Π°Π½ΠΈΠΉ
  • ΠŸΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ (Scheduler) β€” ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΠΉ задания ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ
  • Зависимости (Dependencies) β€” ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ синхронизации ΠΌΠ΅ΠΆΠ΄Ρƒ заданиями

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π·Π°Π΄Π°Π½ΠΈΠΉ

#include "Wudgine/Core/JobSystem.hpp"

// БозданиС задания
Wudgine::Core::Job myJob = []() {
    // Код, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅
    for (int i = 0; i < 1000; i++) {
        // ВычислСния
    }
};

// Запуск задания
Wudgine::Core::JobHandle handle = Wudgine::Core::JobSystem::Schedule(myJob);

// ОТиданиС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ задания
handle.Wait();

Π Π°Π±ΠΎΡ‚Π° с зависимостями

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ задания
Wudgine::Core::Job job1 = []() {
    // ΠŸΠ΅Ρ€Π²Π°Ρ Ρ‡Π°ΡΡ‚ΡŒ вычислСний
};

// Запуск ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ задания
Wudgine::Core::JobHandle handle1 = Wudgine::Core::JobSystem::Schedule(job1);

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ задания, зависящСго ΠΎΡ‚ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ
Wudgine::Core::Job job2 = []() {
    // Вторая Ρ‡Π°ΡΡ‚ΡŒ вычислСний, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΏΠ΅Ρ€Π²ΠΎΠΉ
};

// Запуск Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ задания с Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ‚ΡŒΡŽ ΠΎΡ‚ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ
Wudgine::Core::JobHandle handle2 = Wudgine::Core::JobSystem::Schedule(job2, handle1);

// ОТиданиС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ всСх Π·Π°Π΄Π°Π½ΠΈΠΉ
handle2.Wait(); // НСявно ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Ρ‚Π°ΠΊΠΆΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ handle1

ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ†ΠΈΠΊΠ»Ρ‹

БистСма Π·Π°Π΄Π°Π½ΠΈΠΉ Wudgine прСдоставляСт ΡƒΠ΄ΠΎΠ±Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ выполнСния Ρ†ΠΈΠΊΠ»ΠΎΠ²:

std::vector<Entity> entities(10000);

// ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° массива сущностСй
Wudgine::Core::JobSystem::ParallelFor(0, entities.size(), [&entities](int index) {
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сущности
    ProcessEntity(entities[index]);
});

ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ систСм ECS

Wudgine позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ систСмы ECS ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ, Ρ‡Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ²Ρ‹ΡˆΠ°Π΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ большом количСствС сущностСй.

Настройка ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ выполнСния

class MySystem : public Wudgine::ECS::System {
public:
    MySystem() {
        // Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ систСма ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ
        SetParallelExecution(true);
    }

    void Update(float deltaTime) override {
        // Код систСмы Π±ΡƒΠ΄Π΅Ρ‚ автоматичСски распараллСлСн
        auto view = GetWorld()->GetRegistry().view<ComponentA, ComponentB>();
        
        // Π­Ρ‚ΠΎΡ‚ Ρ†ΠΈΠΊΠ» Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ
        view.each([deltaTime](auto entity, ComponentA& a, ComponentB& b) {
            // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²
        });
    }
};

Зависимости ΠΌΠ΅ΠΆΠ΄Ρƒ систСмами

Для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Ρ… систСм Π²Π°ΠΆΠ½ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ зависимости ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ:

// Π’ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΈΡ€Π° ΠΈΠ»ΠΈ сцСны
void InitializeSystems() {
    auto& world = GetWorld();
    
    // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ систСмы
    auto& physicsSystem = world->AddSystem<PhysicsSystem>();
    auto& animationSystem = world->AddSystem<AnimationSystem>();
    auto& renderSystem = world->AddSystem<RenderSystem>();
    
    // НастраиваСм зависимости
    // AnimationSystem Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС PhysicsSystem
    animationSystem.AddDependency(physicsSystem);
    
    // RenderSystem Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС AnimationSystem
    renderSystem.AddDependency(animationSystem);
}

Асинхронная Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° рСсурсов

Wudgine прСдоставляСт ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ для асинхронной Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ рСсурсов, Ρ‡Ρ‚ΠΎ позволяСт ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π·Π°Π΄Π΅Ρ€ΠΆΠ΅ΠΊ Π²ΠΎ врСмя ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠ³ΠΎ процСсса.

Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° тСкстур

// Асинхронная Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° тСкстуры
Wudgine::Resources::TextureHandle textureHandle = 
    Wudgine::Resources::ResourceManager::LoadTextureAsync("textures/character.png");

// ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° готовности рСсурса
if (textureHandle.IsReady()) {
    // ИспользованиС тСкстуры
    auto& texture = textureHandle.Get();
    // ...
} else {
    // ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π·Π°Π³Π»ΡƒΡˆΠΊΠΈ ΠΈΠ»ΠΈ ΠΈΠ½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ
}

Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ

// Асинхронная Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΌΠΎΠ΄Π΅Π»ΠΈ
Wudgine::Resources::ModelHandle modelHandle = 
    Wudgine::Resources::ResourceManager::LoadModelAsync("models/character.fbx");

// Установка callback-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ
modelHandle.SetOnLoadedCallback([](const Wudgine::Resources::Model& model) {
    // Код, выполняСмый послС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ
    std::cout << "Model loaded with " << model.GetMeshCount() << " meshes" << std::endl;
});

ΠŸΠΎΡ‚ΠΎΠΊΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…

Wudgine прСдоставляСт Π½Π°Π±ΠΎΡ€ потокобСзопасных структур Π΄Π°Π½Π½Ρ‹Ρ… для бСзопасного ΠΎΠ±ΠΌΠ΅Π½Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠ΅ΠΉ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ.

АтомарныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ

#include "Wudgine/Core/Atomic.hpp"

// Атомарный счСтчик
Wudgine::Core::AtomicInt counter(0);

// Π˜Π½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ счСтчика ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
counter.Increment();

// ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ значСния
int value = counter.Get();

ΠŸΠΎΡ‚ΠΎΠΊΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π°Ρ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ

#include "Wudgine/Core/ConcurrentQueue.hpp"

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ потокобСзопасной ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ
Wudgine::Core::ConcurrentQueue<int> queue;

// Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ элСмСнтов (ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· любого ΠΏΠΎΡ‚ΠΎΠΊΠ°)
queue.Push(42);

// Π˜Π·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ элСмСнтов (ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· любого ΠΏΠΎΡ‚ΠΎΠΊΠ°)
int value;
if (queue.TryPop(value)) {
    // УспСшно ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ элСмСнт
    std::cout << "Popped value: " << value << std::endl;
}

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΈ синхронизация

Wudgine прСдоставляСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²Ρ‹ синхронизации для бСзопасного доступа ΠΊ раздСляСмым рСсурсам.

ΠœΡŒΡŽΡ‚Π΅ΠΊΡΡ‹

#include "Wudgine/Core/Mutex.hpp"

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠ°
Wudgine::Core::Mutex mutex;

// Π—Π°Ρ‰ΠΈΡ‚Π° критичСской сСкции
{
    Wudgine::Core::MutexLock lock(mutex);
    // Код, Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‰ΠΈΠΉ эксклюзивного доступа
}

УсловныС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅

#include "Wudgine/Core/ConditionVariable.hpp"

Wudgine::Core::Mutex mutex;
Wudgine::Core::ConditionVariable cv;
bool dataReady = false;

// ΠŸΠΎΡ‚ΠΎΠΊ-ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ
void Producer() {
    // ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…
    
    {
        Wudgine::Core::MutexLock lock(mutex);
        dataReady = true;
    }
    
    // Π£Π²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅ потрСбитСля
    cv.NotifyOne();
}

// ΠŸΠΎΡ‚ΠΎΠΊ-ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΡŒ
void Consumer() {
    Wudgine::Core::MutexLock lock(mutex);
    
    // ОТиданиС готовности Π΄Π°Π½Π½Ρ‹Ρ…
    cv.Wait(lock, []{ return dataReady; });
    
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…
}

Π›ΡƒΡ‡ΡˆΠΈΠ΅ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ программирования

Π˜Π·Π±Π΅Π³Π°ΠΉΡ‚Π΅ Π³ΠΎΠ½ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ…

  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΡ‹ ΠΈΠ»ΠΈ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ раздСляСмых Π΄Π°Π½Π½Ρ‹Ρ…
  • ΠœΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ врСмя Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠΎΠ²
  • По возмоТности ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΏΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ…

ΠœΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ

  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ lock-free Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹, Π³Π΄Π΅ это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ
  • РаздСляйтС Π΄Π°Π½Π½Ρ‹Π΅ Π½Π° нСзависимыС части для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ fine-grained locking вмСсто Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ

ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

  • Π£Ρ‡ΠΈΡ‚Ρ‹Π²Π°ΠΉΡ‚Π΅ кэш-Π»ΠΈΠ½ΠΈΠΈ процСссора ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ структур Π΄Π°Π½Π½Ρ‹Ρ…
  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π½ΡƒΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ для ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹Ρ… расходов
  • БалансируйтС Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ

ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°

Wudgine прСдоставляСт инструмСнты для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°:

  • ΠŸΡ€ΠΎΡ„ΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² β€” Π°Π½Π°Π»ΠΈΠ· Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния Π·Π°Π΄Π°Π½ΠΈΠΉ Π² Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ…
  • Визуализация зависимостСй β€” графичСскоС прСдставлСниС зависимостСй ΠΌΠ΅ΠΆΠ΄Ρƒ заданиями
  • Π”Π΅Ρ‚Π΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π³ΠΎΠ½ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ… β€” инструмСнты для выявлСния ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ синхронизации

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ физичСская симуляция

class ParallelPhysicsSystem : public Wudgine::ECS::System {
public:
    ParallelPhysicsSystem() {
        SetParallelExecution(true);
    }
    
    void Update(float deltaTime) override {
        auto view = GetWorld()->GetRegistry().view<RigidBodyComponent, TransformComponent>();
        
        // Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ пространства Π½Π° сСтку для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ
        std::vector<std::vector<Entity>> spatialGrid = DivideSpatialGrid(view);
        
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π·Π°Π΄Π°Π½ΠΈΠΉ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ячСйки сСтки
        std::vector<Wudgine::Core::JobHandle> handles;
        
        for (auto& cell : spatialGrid) {
            auto handle = Wudgine::Core::JobSystem::Schedule([this, &cell, deltaTime]() {
                // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ„ΠΈΠ·ΠΈΠΊΠΈ для сущностСй Π² ячСйкС
                for (auto entity : cell) {
                    UpdatePhysics(entity, deltaTime);
                }
            });
            
            handles.push_back(handle);
        }
        
        // ОТиданиС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ всСх Π·Π°Π΄Π°Π½ΠΈΠΉ
        for (auto& handle : handles) {
            handle.Wait();
        }
        
        // Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ»Π»ΠΈΠ·ΠΈΠΉ ΠΌΠ΅ΠΆΠ΄Ρƒ ячСйками
        ResolveInterCellCollisions(spatialGrid);
    }
    
private:
    // Π’ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹
};

Асинхронная гСнСрация ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°

class ProceduralTerrainGenerator {
public:
    void GenerateTerrainAsync(int width, int height, float scale) {
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ задания для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠ°Ρ€Ρ‚Ρ‹ высот
        auto heightmapJob = Wudgine::Core::JobSystem::Schedule([this, width, height, scale]() {
            m_HeightMap = GenerateHeightMap(width, height, scale);
        });
        
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ задания для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ тСкстур, зависящСго ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚Ρ‹ высот
        auto textureJob = Wudgine::Core::JobSystem::Schedule([this]() {
            m_DiffuseMap = GenerateDiffuseMap(m_HeightMap);
            m_NormalMap = GenerateNormalMap(m_HeightMap);
        }, heightmapJob);
        
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ задания для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ мСша, зависящСго ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚Ρ‹ высот
        auto meshJob = Wudgine::Core::JobSystem::Schedule([this]() {
            m_Mesh = GenerateMesh(m_HeightMap);
        }, heightmapJob);
        
        // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ задания для Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ сборки, зависящСго ΠΎΡ‚ тСкстур ΠΈ мСша
        m_FinalHandle = Wudgine::Core::JobSystem::Schedule([this]() {
            m_Terrain = CreateTerrain(m_Mesh, m_DiffuseMap, m_NormalMap);
            m_IsReady = true;
            
            if (m_OnCompletedCallback) {
                m_OnCompletedCallback(m_Terrain);
            }
        }, Wudgine::Core::JobHandle::CombineDependencies(textureJob, meshJob));
    }
    
    bool IsReady() const { return m_IsReady; }
    
    void SetOnCompletedCallback(std::function<void(const Terrain&)> callback) {
        m_OnCompletedCallback = std::move(callback);
    }
    
private:
    // Π”Π°Π½Π½Ρ‹Π΅ ΠΈ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹
    HeightMap m_HeightMap;
    Texture m_DiffuseMap;
    Texture m_NormalMap;
    Mesh m_Mesh;
    Terrain m_Terrain;
    
    bool m_IsReady = false;
    Wudgine::Core::JobHandle m_FinalHandle;
    std::function<void(const Terrain&)> m_OnCompletedCallback;
};

Π§Ρ‚ΠΎ дальшС?

ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ слоТным ΠΈ ΠΏΠΎΠ΄Π²Π΅Ρ€ΠΆΠ΅Π½Π½Ρ‹ΠΌ ошибкам. ВсСгда Ρ‚Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ тСстируйтС ваш ΠΊΠΎΠ΄ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ инструмСнты профилирования для выявлСния ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΈ синхронизации.

Wudgine β€’ Β© 2025