Merge pull request #5532 from aws-lumberyard-dev/optimization/unused_files
Optimization: remove unused files
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#define AZCORE_BUILD_NUMBER 368
|
||||
#define AZCORE_BUILD_DATE "Thu 10/10/2013"
|
||||
#define AZCORE_BUILD_TIME "19:42:16.96"
|
||||
#define AZCORE_SOURCE_CHANGELIST 2992189
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#ifndef AZCORE_JOBS_JOBEXECUTOR_H
|
||||
#define AZCORE_JOBS_JOBEXECUTOR_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/std/parallel/condition_variable.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
/**
|
||||
* Helper for porting legacy jobs that allows Starting and Waiting for multiple jobs asynchronously
|
||||
*/
|
||||
class LegacyJobExecutor final
|
||||
{
|
||||
public:
|
||||
LegacyJobExecutor() = default;
|
||||
|
||||
LegacyJobExecutor(const LegacyJobExecutor&) = delete;
|
||||
|
||||
~LegacyJobExecutor()
|
||||
{
|
||||
WaitForCompletion();
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
inline void StartJob(const Function& processFunction, JobContext* context = nullptr)
|
||||
{
|
||||
Job * job = aznew JobFunctionExecutorHelper<Function>(processFunction, *this, context);
|
||||
StartJobInternal(job);
|
||||
}
|
||||
|
||||
// SetPostJob - This API exists to support backwards compatibility and is not a recommended pattern to be copied.
|
||||
// Instead, create AZ::Jobs with appropriate dependencies on each other
|
||||
template <class Function>
|
||||
inline void SetPostJob(LegacyJobExecutor& postJobExecutor, const Function& processFunction, JobContext* context = nullptr)
|
||||
{
|
||||
AZStd::unique_ptr<JobExecutorHelper> postJob(aznew JobFunctionExecutorHelper<Function>(processFunction, postJobExecutor, context)); // Allocate outside the lock
|
||||
{
|
||||
LockGuard lockGuard(m_conditionLock);
|
||||
|
||||
AZ_Assert(!m_postJob, "Post already set");
|
||||
AZ_Assert(!m_running, "LegacyJobExecutor::SetPostJob() must be called before starting any jobs");
|
||||
m_postJob = std::move(postJob);
|
||||
// Note: m_jobCount is not incremented until we push the post job
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearPostJob()
|
||||
{
|
||||
LockGuard lockGuard(m_conditionLock);
|
||||
m_postJob.reset();
|
||||
}
|
||||
|
||||
inline void Reset()
|
||||
{
|
||||
AZ_Assert(!IsRunning(), "LegacyJobExecutor::Reset() called while jobs in flight");
|
||||
}
|
||||
|
||||
inline void WaitForCompletion()
|
||||
{
|
||||
AZStd::unique_lock<decltype(m_conditionLock)> uniqueLock(m_conditionLock);
|
||||
|
||||
while (m_running)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzCore);
|
||||
m_completionCondition.wait(uniqueLock, [this] { return !this->m_running; });
|
||||
}
|
||||
}
|
||||
|
||||
// Push a logical fence that will cause WaitForCompletion to wait until PopCompletionFence is called and all jobs are complete. Analogue to the legacy API SJobState::SetStarted()
|
||||
// Note: this does NOT fence execution of jobs in relation to each other
|
||||
inline void PushCompletionFence()
|
||||
{
|
||||
IncJobCount();
|
||||
}
|
||||
|
||||
// Pop a logical completion fence. Analogue to the legacy API SJobState::SetStopped()
|
||||
inline void PopCompletionFence()
|
||||
{
|
||||
JobCompleteUpdate();
|
||||
}
|
||||
|
||||
// Are there presently jobs in-flight (queued or running)?
|
||||
inline bool IsRunning()
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
private:
|
||||
void JobCompleteUpdate()
|
||||
{
|
||||
AZ_Assert(m_jobCount, "Invalid LegacyJobExecutor::m_jobCount.");
|
||||
if (--m_jobCount == 0) // note: m_jobCount is atomic, so only the last completing job will take the count to zero
|
||||
{
|
||||
JobExecutorHelper* postJob = nullptr;
|
||||
{
|
||||
// All state transitions to and from running must be serialized through the condition lock
|
||||
LockGuard lockGuard(m_conditionLock);
|
||||
|
||||
// Test count again as another job may have started before we got the lock
|
||||
if (!m_jobCount)
|
||||
{
|
||||
m_running = false;
|
||||
postJob = m_postJob.release();
|
||||
m_completionCondition.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// outside the lock (this pointer is no longer valid)...
|
||||
if (postJob)
|
||||
{
|
||||
postJob->StartOnExecutor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartJobInternal(Job * job)
|
||||
{
|
||||
IncJobCount();
|
||||
job->Start();
|
||||
}
|
||||
|
||||
void IncJobCount()
|
||||
{
|
||||
if (m_jobCount++ == 0)
|
||||
{
|
||||
// All state transitions to and from running must be serialized through the condition lock (Even though m_running is atomic)
|
||||
LockGuard lockGuard(m_conditionLock);
|
||||
m_running = true;
|
||||
}
|
||||
}
|
||||
|
||||
class JobExecutorHelper
|
||||
{
|
||||
public:
|
||||
virtual ~JobExecutorHelper() = default;
|
||||
virtual void StartOnExecutor() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Private Job type that notifies the owning LegacyJobExecutor of completion
|
||||
*/
|
||||
template<class Function>
|
||||
class JobFunctionExecutorHelper : public JobFunction<Function>, public JobExecutorHelper
|
||||
{
|
||||
using Base = JobFunction<Function>;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(JobFunctionExecutorHelper, ThreadPoolAllocator, 0)
|
||||
|
||||
JobFunctionExecutorHelper(typename JobFunction<Function>::FunctionCRef processFunction, LegacyJobExecutor& executor, JobContext* context)
|
||||
: JobFunction<Function>(processFunction, true /* isAutoDelete */, context)
|
||||
, m_executor(executor)
|
||||
{
|
||||
}
|
||||
|
||||
void StartOnExecutor() override
|
||||
{
|
||||
m_executor.StartJobInternal(this);
|
||||
}
|
||||
|
||||
void Process() override
|
||||
{
|
||||
Base::Process();
|
||||
|
||||
m_executor.JobCompleteUpdate();
|
||||
}
|
||||
|
||||
private:
|
||||
LegacyJobExecutor& m_executor;
|
||||
};
|
||||
|
||||
template<class Function>
|
||||
friend class JobFunctionExecutorHelper; // For JobCompleteUpdate, StartJobInternal
|
||||
|
||||
using Lock = AZStd::mutex;
|
||||
using LockGuard = AZStd::lock_guard<Lock>;
|
||||
|
||||
AZStd::condition_variable m_completionCondition;
|
||||
Lock m_conditionLock;
|
||||
AZStd::unique_ptr<JobExecutorHelper> m_postJob;
|
||||
|
||||
AZStd::atomic_uint m_jobCount{0};
|
||||
AZStd::atomic_bool m_running{false};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -7,22 +7,8 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/parallel/containers/concurrent_fixed_unordered_set.h>
|
||||
|
||||
#include <AzCore/Memory/AllocatorManager.h>
|
||||
|
||||
AZ::AllocatorStorage::LazyAllocatorRef::~LazyAllocatorRef()
|
||||
{
|
||||
m_destructor(*m_allocator);
|
||||
}
|
||||
|
||||
void AZ::AllocatorStorage::LazyAllocatorRef::Init(size_t size, size_t alignment, CreationFn creationFn, DestructionFn destructionFn)
|
||||
{
|
||||
m_allocator = AZ::AllocatorManager::CreateLazyAllocator(size, alignment, creationFn);
|
||||
m_destructor = destructionFn;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// New overloads
|
||||
|
||||
@@ -521,19 +521,6 @@ namespace AZ
|
||||
{
|
||||
namespace AllocatorStorage
|
||||
{
|
||||
/// A private structure to create heap-storage for an allocator that won't expire until other static module members are destructed.
|
||||
struct LazyAllocatorRef
|
||||
{
|
||||
using CreationFn = IAllocator*(*)(void*);
|
||||
using DestructionFn = void(*)(IAllocator&);
|
||||
|
||||
~LazyAllocatorRef();
|
||||
void Init(size_t size, size_t alignment, CreationFn creationFn, DestructionFn destructionFn);
|
||||
|
||||
IAllocator* m_allocator = nullptr;
|
||||
DestructionFn m_destructor = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* A base class for all storage policies. This exists to provide access to private IAllocator methods via template friends.
|
||||
*/
|
||||
@@ -640,87 +627,6 @@ namespace AZ
|
||||
|
||||
template<class Allocator>
|
||||
EnvironmentVariable<Allocator> EnvironmentStoragePolicy<Allocator>::s_allocator;
|
||||
|
||||
/**
|
||||
* ModuleStoragePolicy stores the allocator in a static variable that is local to the module using it.
|
||||
* This forces separate instances of the allocator to exist in each module, and permits lazy instantiation.
|
||||
* We only tolerate this for some special allocators, primarily to maintain backwards compatibility with CryEngine,
|
||||
* since it still allocates outside of code in the data section.
|
||||
*
|
||||
* It has two ways of storing its allocator: either on the heap, which is the preferred way, since it guarantees
|
||||
* the memory for the allocator won't be deallocated (such as in a DLL) before anyone that's using it. If disabled
|
||||
* the allocator is stored in a static variable, which should only be used where this isn't a problem a shut-down
|
||||
* time, such as on a console.
|
||||
*/
|
||||
template<class Allocator, bool StoreAllocatorOnHeap>
|
||||
struct ModuleStoragePolicyBase;
|
||||
|
||||
template<class Allocator>
|
||||
struct ModuleStoragePolicyBase<Allocator, false>: public StoragePolicyBase<Allocator>
|
||||
{
|
||||
protected:
|
||||
// Use a static instance to store the allocator. This is not recommended when the order of shut-down with the module matters, as the allocator could have its memory destroyed
|
||||
// before the users of it are destroyed. The primary use case for this is allocators that need to support the CRT, as they cannot allocate from the heap.
|
||||
static Allocator& GetModuleAllocatorInstance()
|
||||
{
|
||||
static Allocator* s_allocator = nullptr;
|
||||
static typename AZStd::aligned_storage<sizeof(Allocator), AZStd::alignment_of<Allocator>::value>::type s_storage;
|
||||
|
||||
if (!s_allocator)
|
||||
{
|
||||
s_allocator = new (&s_storage) Allocator;
|
||||
StoragePolicyBase<Allocator>::Create(*s_allocator, typename Allocator::Descriptor(), true);
|
||||
}
|
||||
|
||||
return *s_allocator;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct ModuleStoragePolicyBase<Allocator, true> : public StoragePolicyBase<Allocator>
|
||||
{
|
||||
protected:
|
||||
// Store-on-heap implementation uses the LazyAllocatorRef to create and destroy an allocator using heap-space so there isn't a problem with destruction order within the module.
|
||||
static Allocator& GetModuleAllocatorInstance()
|
||||
{
|
||||
static LazyAllocatorRef s_allocator;
|
||||
|
||||
if (!s_allocator.m_allocator)
|
||||
{
|
||||
s_allocator.Init(sizeof(Allocator), AZStd::alignment_of<Allocator>::value, [](void* mem) -> IAllocator* { return new (mem) Allocator; }, &StoragePolicyBase<Allocator>::Destroy);
|
||||
StoragePolicyBase<Allocator>::Create(*static_cast<Allocator*>(s_allocator.m_allocator), typename Allocator::Descriptor(), true);
|
||||
}
|
||||
|
||||
return *static_cast<Allocator*>(s_allocator.m_allocator);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator, bool StoreAllocatorOnHeap = true>
|
||||
class ModuleStoragePolicy : public ModuleStoragePolicyBase<Allocator, StoreAllocatorOnHeap>
|
||||
{
|
||||
public:
|
||||
using Base = ModuleStoragePolicyBase<Allocator, StoreAllocatorOnHeap>;
|
||||
|
||||
static IAllocator& GetAllocator()
|
||||
{
|
||||
return Base::GetModuleAllocatorInstance();
|
||||
}
|
||||
|
||||
static void Create(const typename Allocator::Descriptor& desc = typename Allocator::Descriptor())
|
||||
{
|
||||
StoragePolicyBase<Allocator>::Create(Base::GetModuleAllocatorInstance(), desc, true);
|
||||
}
|
||||
|
||||
static void Destroy()
|
||||
{
|
||||
StoragePolicyBase<Allocator>::Destroy(Base::GetModuleAllocatorInstance());
|
||||
}
|
||||
|
||||
static bool IsReady()
|
||||
{
|
||||
return Base::GetModuleAllocatorInstance().IsReady();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimeDataStatisticsManager.h"
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Statistics
|
||||
{
|
||||
void TimeDataStatisticsManager::PushTimeDataSample(const char * registerName, const AZ::Debug::ProfilerRegister::TimeData& timeData)
|
||||
{
|
||||
const AZStd::string statName(registerName);
|
||||
NamedRunningStatistic* statistic = GetStatistic(statName);
|
||||
if (!statistic)
|
||||
{
|
||||
const AZStd::string units("us");
|
||||
AddStatistic(statName, statName, units, false);
|
||||
AZ::Debug::ProfilerRegister::TimeData zeroTimeData;
|
||||
memset(&zeroTimeData, 0, sizeof(AZ::Debug::ProfilerRegister::TimeData));
|
||||
m_previousTimeData[statName] = zeroTimeData;
|
||||
statistic = GetStatistic(statName);
|
||||
AZ_Assert(statistic != nullptr, "Fatal error adding a new statistic object");
|
||||
}
|
||||
|
||||
const AZ::u64 accumulatedTime = timeData.m_time;
|
||||
const AZ::s64 totalNumCalls = timeData.m_calls;
|
||||
const AZ::u64 previousAccumulatedTime = m_previousTimeData[statName].m_time;
|
||||
const AZ::s64 previousTotalNumCalls = m_previousTimeData[statName].m_calls;
|
||||
const AZ::u64 deltaTime = accumulatedTime - previousAccumulatedTime;
|
||||
const AZ::s64 deltaCalls = totalNumCalls - previousTotalNumCalls;
|
||||
|
||||
if (deltaCalls == 0)
|
||||
{
|
||||
//This is the same old data. Let's skip it
|
||||
return;
|
||||
}
|
||||
|
||||
double newSample = static_cast<double>(deltaTime) / deltaCalls;
|
||||
|
||||
statistic->PushSample(newSample);
|
||||
m_previousTimeData[statName] = timeData;
|
||||
}
|
||||
} //namespace Statistics
|
||||
} //namespace AZ
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Statistics/StatisticsManager.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Statistics
|
||||
{
|
||||
/**
|
||||
* @brief Specialization useful for data generated with AZ::Debug::FrameProfileComponent
|
||||
*
|
||||
* Timer based data collection using AZ_PROFILE_TIMER(...), available in
|
||||
* AzCore/Debug/Profiler.h can be collected when using AZ::Debug::FrameProfilerComponent
|
||||
* and AZ::Debug::FrameProfilerBus. The method PushTimeDataSample(...) is a convenience
|
||||
* to convert those Timer registers into a RunningStatistic.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class TimeDataStatisticsManager : public StatisticsManager<>
|
||||
{
|
||||
public:
|
||||
TimeDataStatisticsManager() = default;
|
||||
virtual ~TimeDataStatisticsManager() = default;
|
||||
|
||||
/**
|
||||
* @brief Adds one sample data to a specific running stat by name.
|
||||
*
|
||||
* This method is specialized to work with ProfilerRegister::TimeData that can be intercepted
|
||||
* during AZ::Debug::FrameProfilerBus::OnFrameProfilerData().
|
||||
* For each @param registerName a new RunningStat object is created if it doesn't exist.
|
||||
*
|
||||
* Adds the TimeData as one sample for its RunningStatistic.
|
||||
*/
|
||||
void PushTimeDataSample(const char * registerName, const AZ::Debug::ProfilerRegister::TimeData& timeData);
|
||||
|
||||
protected:
|
||||
///We store here the previous value from the previous timer frame data.
|
||||
///This is necessary because AZ_PROFILER_TIMER is cumulative
|
||||
///and we need the time spent for each call.
|
||||
AZStd::unordered_map<AZStd::string, AZ::Debug::ProfilerRegister::TimeData> m_previousTimeData;
|
||||
};
|
||||
} //namespace Statistics
|
||||
} //namespace AZ
|
||||
@@ -240,7 +240,6 @@ set(FILES
|
||||
Jobs/JobManagerComponent.cpp
|
||||
Jobs/JobManagerComponent.h
|
||||
Jobs/JobManagerDesc.h
|
||||
Jobs/LegacyJobExecutor.h
|
||||
Jobs/MultipleDependentJob.h
|
||||
Jobs/task_group.h
|
||||
Math/Aabb.cpp
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <AzCore/Jobs/JobCompletion.h>
|
||||
#include <AzCore/Jobs/JobCompletionSpin.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/Jobs/LegacyJobExecutor.h>
|
||||
#include <AzCore/Jobs/JobManager.h>
|
||||
#include <AzCore/Jobs/task_group.h>
|
||||
#include <AzCore/Jobs/Algorithms.h>
|
||||
@@ -1398,103 +1397,6 @@ namespace UnitTest
|
||||
run();
|
||||
}
|
||||
|
||||
using JobLegacyJobExecutorIsRunning = DefaultJobManagerSetupFixture;
|
||||
TEST_F(JobLegacyJobExecutorIsRunning, Test)
|
||||
{
|
||||
// Note: Legacy JobExecutor exists as an adapter to Legacy CryEngine jobs.
|
||||
// When writing new jobs instead favor direct use of the AZ::Job type family
|
||||
AZ::LegacyJobExecutor jobExecutor;
|
||||
EXPECT_FALSE(jobExecutor.IsRunning());
|
||||
|
||||
// Completion fences and IsRunning()
|
||||
{
|
||||
jobExecutor.PushCompletionFence();
|
||||
EXPECT_TRUE(jobExecutor.IsRunning());
|
||||
jobExecutor.PopCompletionFence();
|
||||
EXPECT_FALSE(jobExecutor.IsRunning());
|
||||
}
|
||||
|
||||
AZStd::atomic_bool jobExecuted{ false };
|
||||
AZStd::binary_semaphore jobSemaphore;
|
||||
|
||||
jobExecutor.StartJob([&jobSemaphore, &jobExecuted]
|
||||
{
|
||||
// Wait until the test thread releases
|
||||
jobExecuted = true;
|
||||
jobSemaphore.acquire();
|
||||
}
|
||||
);
|
||||
EXPECT_TRUE(jobExecutor.IsRunning());
|
||||
|
||||
// Allow the job to complete
|
||||
jobSemaphore.release();
|
||||
|
||||
// Wait for completion
|
||||
jobExecutor.WaitForCompletion();
|
||||
EXPECT_FALSE(jobExecutor.IsRunning());
|
||||
EXPECT_TRUE(jobExecuted);
|
||||
}
|
||||
|
||||
using JobLegacyJobExecutorWaitForCompletion = DefaultJobManagerSetupFixture;
|
||||
TEST_F(JobLegacyJobExecutorWaitForCompletion, Test)
|
||||
{
|
||||
// Note: Legacy JobExecutor exists as an adapter to Legacy CryEngine jobs.
|
||||
// When writing new jobs instead favor direct use of the AZ::Job type family
|
||||
AZ::LegacyJobExecutor jobExecutor;
|
||||
|
||||
// Semaphores used to park job threads until released
|
||||
const AZ::u32 numParkJobs = AZ::JobContext::GetGlobalContext()->GetJobManager().GetNumWorkerThreads();
|
||||
AZStd::vector<AZStd::binary_semaphore> jobSemaphores(numParkJobs);
|
||||
|
||||
// Data destination for workers
|
||||
const AZ::u32 workJobCount = numParkJobs * 2;
|
||||
AZStd::vector<AZ::u32> jobData(workJobCount, 0);
|
||||
|
||||
// Touch completion multiple times as a test of correctly transitioning in and out of the all jobs completed state
|
||||
AZ::u32 NumCompletionCycles = 5;
|
||||
for (AZ::u32 completionItrIdx = 0; completionItrIdx < NumCompletionCycles; ++completionItrIdx)
|
||||
{
|
||||
// Intentionally park every job thread
|
||||
for (auto& jobSemaphore : jobSemaphores)
|
||||
{
|
||||
jobExecutor.StartJob([&jobSemaphore]
|
||||
{
|
||||
jobSemaphore.acquire();
|
||||
}
|
||||
);
|
||||
}
|
||||
EXPECT_TRUE(jobExecutor.IsRunning());
|
||||
|
||||
// Kick off verifiable "work" jobs
|
||||
for (AZ::u32 i = 0; i < workJobCount; ++i)
|
||||
{
|
||||
jobExecutor.StartJob([i, &jobData]
|
||||
{
|
||||
jobData[i] = i + 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
EXPECT_TRUE(jobExecutor.IsRunning());
|
||||
|
||||
// Now released our parked job threads
|
||||
for (auto& jobSemaphore : jobSemaphores)
|
||||
{
|
||||
jobSemaphore.release();
|
||||
}
|
||||
|
||||
// And wait for all jobs to finish
|
||||
jobExecutor.WaitForCompletion();
|
||||
EXPECT_FALSE(jobExecutor.IsRunning());
|
||||
|
||||
// Verify our workers ran and clear data
|
||||
for (size_t i = 0; i < workJobCount; ++i)
|
||||
{
|
||||
EXPECT_EQ(jobData[i], i + 1);
|
||||
jobData[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JobCompletionCompleteNotScheduled
|
||||
: public DefaultJobManagerSetupFixture
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user