bool ezPipeChannel_win::ProcessOutgoingMessages(DWORD uiBytesWritten)
{
  EZ_ASSERT_DEBUG(m_Connected, "Must be connected to process outgoing messages.");
  EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!");

  if (m_OutputState.IsPending)
  {
    if (uiBytesWritten == 0)
    {
      // Don't reset isPending right away as we want to use it to decide
      // whether we need to wake up the worker thread again.
      ezLog::Error("pipe error: {0}", ezArgErrorCode(GetLastError()));
      m_OutputState.IsPending = false;
      return false;
    }

    EZ_LOCK(m_OutputQueueMutex);
    //message was send
    m_OutputQueue.PopFront();
  }

  if (m_PipeHandle == INVALID_HANDLE_VALUE)
  {
    m_OutputState.IsPending = false;
    return false;
  }
  const ezMemoryStreamStorage* storage = nullptr;
  {
    EZ_LOCK(m_OutputQueueMutex);
    if (m_OutputQueue.IsEmpty())
    {
      m_OutputState.IsPending = false;
      return true;
    }
    storage = &m_OutputQueue.PeekFront();
  }

  BOOL res = WriteFile(m_PipeHandle, storage->GetData(), storage->GetStorageSize(), &uiBytesWritten,
                       &m_OutputState.Context.Overlapped);

  if (!res)
  {
    ezUInt32 error = GetLastError();
    if (error == ERROR_IO_PENDING)
    {
      m_OutputState.IsPending = true;
      return true;
    }
    ezLog::Error("Write to pipe failed: {0}", ezArgErrorCode(error));
    return false;
  }

  m_OutputState.IsPending = true;
  return true;
}
void ezPipeChannel_win::OnIOCompleted(IOContext* pContext, DWORD uiBytesTransfered, DWORD uiError)
{
  EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!");
  bool bRes = true;
  if (pContext == &m_InputState.Context)
  {
    if (!m_Connected)
    {
      if (!ProcessConnection())
        return;

      bool bHasOutput = false;
      {
        EZ_LOCK(m_OutputQueueMutex);
        bHasOutput = !m_OutputQueue.IsEmpty();
      }

      if (bHasOutput && m_OutputState.IsPending == 0)
        ProcessOutgoingMessages(0);
      if (m_InputState.IsPending)
        return;
    }
    bRes = ProcessIncomingMessages(uiBytesTransfered);
  }
  else
  {
    EZ_ASSERT_DEBUG(pContext == &m_OutputState.Context, "");
    bRes = ProcessOutgoingMessages(uiBytesTransfered);
  }
  if (!bRes && m_PipeHandle != INVALID_HANDLE_VALUE)
  {
    InternalDisconnect();
  }
}
void ezPipeChannel_win::InternalDisconnect()
{
#if EZ_ENABLED(EZ_COMPILE_FOR_DEBUG)
  if (m_ThreadId != 0)
    EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!");
#endif
  if (m_InputState.IsPending || m_OutputState.IsPending)
  {
    CancelIo(m_PipeHandle);
  }

  if (m_PipeHandle != INVALID_HANDLE_VALUE)
  {
    CloseHandle(m_PipeHandle);
    m_PipeHandle = INVALID_HANDLE_VALUE;
  }

  while (m_InputState.IsPending || m_OutputState.IsPending)
  {
    FlushPendingOperations();
  }

  {
    EZ_LOCK(m_OutputQueueMutex);
    m_OutputQueue.Clear();
    m_Connected = false;
  }

  m_Events.Broadcast(ezIpcChannelEvent(m_Mode == Mode::Client ? ezIpcChannelEvent::DisconnectedFromServer : ezIpcChannelEvent::DisconnectedFromClient, this));
  // Raise in case another thread is waiting for new messages (as we would sleep forever otherwise).
  m_IncomingMessages.RaiseSignal();
}
Exemple #4
0
void ezTaskSystem::TaskHasFinished(ezTask* pTask, ezTaskGroup* pGroup)
{
  // this might deallocate the task, make sure not to reference it later anymore
  if (pTask && pTask->m_OnTaskFinished.IsValid())
    pTask->m_OnTaskFinished(pTask);

  if (pGroup->m_iRemainingTasks.Decrement() == 0)
  {
    // If this was the last task that had to be finished from this group, make sure all dependent groups are started

    if (!pGroup->m_OthersDependingOnMe.IsEmpty())
    {
      EZ_LOCK(s_TaskSystemMutex);

      for (ezUInt32 dep = 0; dep < pGroup->m_OthersDependingOnMe.GetCount(); ++dep)
      {
        DependencyHasFinished(pGroup->m_OthersDependingOnMe[dep].m_pTaskGroup);
      }
    }

    if (pGroup->m_OnFinishedCallback.IsValid())
      pGroup->m_OnFinishedCallback();

    // set this task group to be finished and available for reuse
    pGroup->m_uiGroupCounter += 2;
    pGroup->m_bInUse = false;
  }
}
Exemple #5
0
ezResult ezTaskSystem::CancelTask(ezTask* pTask, ezOnTaskRunning::Enum OnTaskRunning)
{
  if (pTask->IsTaskFinished())
    return EZ_SUCCESS;

  EZ_PROFILE_SCOPE("CancelTask");

  EZ_ASSERT_DEV(pTask->m_BelongsToGroup.m_pTaskGroup->m_uiGroupCounter == pTask->m_BelongsToGroup.m_uiGroupCounter,
                "The task to be removed is in an invalid group.");

  // we set the cancel flag, to make sure that tasks that support canceling will terminate asap
  pTask->m_bCancelExecution = true;

  {
    EZ_LOCK(s_TaskSystemMutex);

    // if the task is still in the queue of its group, it had not yet been scheduled
    if (!pTask->m_bTaskIsScheduled && pTask->m_BelongsToGroup.m_pTaskGroup->m_Tasks.RemoveAndSwap(pTask))
    {
      // we set the task to finished, even though it was not executed
      pTask->m_bIsFinished = true;
      return EZ_SUCCESS;
    }

    // check if the task has already been scheduled for execution
    // if so, remove it from the work queue
    {
      for (ezUInt32 i = 0; i < ezTaskPriority::ENUM_COUNT; ++i)
      {
        auto it = s_Tasks[i].GetIterator();

        while (it.IsValid())
        {
          if (it->m_pTask == pTask)
          {
            s_Tasks[i].Remove(it);

            // we set the task to finished, even though it was not executed
            pTask->m_bIsFinished = true;

            // tell the system that one task of that group is 'finished', to ensure its dependencies will get scheduled
            TaskHasFinished(it->m_pTask, it->m_pBelongsToGroup);
            return EZ_SUCCESS;
          }

          ++it;
        }
      }
    }
  }

  // if we made it here, the task was already running
  // thus we just wait for it to finish

  if (OnTaskRunning == ezOnTaskRunning::WaitTillFinished)
    WaitForTask(pTask);

  return EZ_FAILURE;
}
ezHashedString ezMaterialResource::GetPermutationValue(const ezTempHashedString& sName)
{
  UpdateCaches();

  EZ_LOCK(m_CacheMutex);

  ezHashedString sResult;
  m_CachedPermutationVars.TryGetValue(sName, sResult);

  return sResult;
}
ezVariant ezMaterialResource::GetParameter(const ezTempHashedString& sName)
{
  EZ_LOCK(m_CacheMutex);

  UpdateCaches();

  ezVariant value;
  m_CachedParameters.TryGetValue(sName, value);

  return value;
}
ezTextureCubeResourceHandle ezMaterialResource::GetTextureCubeBinding(const ezTempHashedString& sName)
{
  EZ_LOCK(m_CacheMutex);

  UpdateCaches();

  // Use pointer to prevent ref counting
  ezTextureCubeResourceHandle* pBinding;
  if (m_CachedTextureCubeBindings.TryGetValue(sName, pBinding))
  {
    return *pBinding;
  }

  return ezTextureCubeResourceHandle();
}
void ezCollectionResource::UnregisterNames()
{
  if (!m_bRegistered)
    return;

  m_bRegistered = false;

  EZ_LOCK(ezResourceManager::GetMutex());

  for (const auto& entry : m_Collection.m_Resources)
  {
    if (!entry.m_sLookupName.IsEmpty())
    {
      ezResourceManager::UnregisterNamedResource(entry.m_sLookupName);
    }
  }
}
Exemple #10
0
void ezStats::RemoveStat(const char* szStatName)
{
  EZ_LOCK(s_Mutex);

  MapType::Iterator it = s_Stats.Find(szStatName);

  if (!it.IsValid())
    return;

  s_Stats.Remove(it);

  StatsEventData e;
  e.m_EventType = StatsEventData::Remove;
  e.m_szStatName = szStatName;

  s_StatsEvents.Broadcast(e);
}
Exemple #11
0
void ezStats::SetStat(const char* szStatName, const ezVariant& value)
{
  EZ_LOCK(s_Mutex);

  bool bExisted = false;
  auto it = s_Stats.FindOrAdd(szStatName, &bExisted);

  if (it.Value() == value)
    return;

  it.Value() = value;

  StatsEventData e;
  e.m_EventType = bExisted ? StatsEventData::Set : StatsEventData::Add;
  e.m_szStatName = szStatName;
  e.m_NewStatValue = value;

  s_StatsEvents.Broadcast(e);
}
Exemple #12
0
bool ezSceneViewContext::UpdateThumbnailCamera(const ezBoundingBoxSphere& bounds)
{
  ezView* pView = nullptr;
  if (ezRenderWorld::TryGetView(m_hView, pView))
  {
    pView->SetViewRenderMode(ezViewRenderMode::Default);
    pView->SetRenderPassProperty("EditorSelectionPass", "Active", false);
    pView->SetExtractorProperty("EditorShapeIconsExtractor", "Active", false);
    pView->SetExtractorProperty("EditorGridExtractor", "Active", false);
    pView->SetRenderPassProperty("EditorPickingPass", "PickSelected", true);
  }

  EZ_LOCK(m_pSceneContext->GetWorld()->GetWriteMarker());
  const ezCameraComponentManager* pCamMan = m_pSceneContext->GetWorld()->GetComponentManager<ezCameraComponentManager>();
  if (pCamMan)
  {
    for (auto it = pCamMan->GetComponents(); it.IsValid(); ++it)
    {
      const ezCameraComponent* pCamComp = it;

      if (pCamComp->GetUsageHint() == ezCameraUsageHint::Thumbnail)
      {
        m_Camera.LookAt(pCamComp->GetOwner()->GetGlobalPosition(),
                        pCamComp->GetOwner()->GetGlobalPosition() + pCamComp->GetOwner()->GetGlobalDirForwards(),
                        pCamComp->GetOwner()->GetGlobalDirUp());

        m_Camera.SetCameraMode(ezCameraMode::PerspectiveFixedFovY, 70.0f, 0.1f, 100.0f);

        m_CullingCamera = m_Camera;
        return true;
      }
    }
  }

  bool bResult = !FocusCameraOnObject(m_Camera, bounds, 70.0f, -ezVec3(5, -2, 3));
  m_CullingCamera = m_Camera;
  return bResult;
}
Exemple #13
0
void ezTokenizedFileCache::Remove(const ezString& sFileName)
{
  EZ_LOCK(m_Mutex);
  m_Cache.Remove(sFileName);
}
Exemple #14
0
ezMap<ezString, ezTokenizedFileCache::FileData>::ConstIterator ezTokenizedFileCache::Lookup(const ezString& sFileName) const
{
  EZ_LOCK(m_Mutex);
  auto it = m_Cache.Find(sFileName);
  return it;
}
Exemple #15
0
const ezTokenizer* ezTokenizedFileCache::Tokenize(const ezString& sFileName, const ezDynamicArray<ezUInt8>& FileContent, const ezTimestamp& FileTimeStamp, ezLogInterface* pLog)
{
  EZ_LOCK(m_Mutex);

  auto& data = m_Cache[sFileName];

  data.m_Timestamp = FileTimeStamp;
  ezTokenizer* pTokenizer = &data.m_Tokens;
  pTokenizer->Tokenize(FileContent, pLog);

  ezDeque<ezToken>& Tokens = pTokenizer->GetTokens();

  ezHashedString sFile;
  sFile.Assign(sFileName.GetData());

  ezInt32 iLineOffset = 0;

  for (ezUInt32 i = 0; i + 1 < Tokens.GetCount(); ++i)
  {
    const ezUInt32 uiCurLine = Tokens[i].m_uiLine;

    Tokens[i].m_File = sFile;
    Tokens[i].m_uiLine += iLineOffset;

    if (Tokens[i].m_iType == ezTokenType::NonIdentifier &&
        ezString(Tokens[i].m_DataView) == "#")
    {
      ezUInt32 uiNext = i + 1;

      SkipWhitespace(Tokens, uiNext);

      if (uiNext < Tokens.GetCount() && 
          Tokens[uiNext].m_iType == ezTokenType::Identifier &&
          ezString(Tokens[uiNext].m_DataView) == "line")
      {
        ++uiNext;
        SkipWhitespace(Tokens, uiNext);

        if (uiNext < Tokens.GetCount() && 
            Tokens[uiNext].m_iType == ezTokenType::Identifier)
        {
          ezInt32 iNextLine = 0;

          const ezString sNumber = Tokens[uiNext].m_DataView;
          if (ezConversionUtils::StringToInt(sNumber.GetData(), iNextLine).Succeeded())
          {
            iLineOffset = (iNextLine - uiCurLine) - 1;

            ++uiNext;
            SkipWhitespace(Tokens, uiNext);

            if (uiNext < Tokens.GetCount())
            {
              if (Tokens[uiNext].m_iType == ezTokenType::String1)
              {
                ezStringBuilder sFileName = Tokens[uiNext].m_DataView;
                sFileName.Shrink(1, 1); // remove surrounding "

                sFile.Assign(sFileName.GetData());
              }
            }
          }
        }
      }
    }
  }

  return pTokenizer;
}
Exemple #16
0
void ezTokenizedFileCache::Clear()
{
  EZ_LOCK(m_Mutex);
  m_Cache.Clear();
}
Exemple #17
0
ezTaskSystem::TaskData ezTaskSystem::GetNextTask(ezTaskPriority::Enum FirstPriority, ezTaskPriority::Enum LastPriority,
                                                 ezTask* pPrioritizeThis)
{
  // this is the central function that selects tasks for the worker threads to work on

  // do a quick and dirty check, whether we would find any work (without a lock)
  // if nothing is found, the thread can go to sleep, without entering the mutex

  // note: There is NO race condition here. Even if this loop would miss a work item, because it is added after it looked at the
  // corresponding queue, it will not be a problem. The function will return with 'no work' for the thread,  the thread will try to go to
  // sleep, but the thread-signal will be signaled already and thus the thread will loop again, call 'GetNextTask' a second time and THEN
  // detect the new work item

  EZ_ASSERT_DEV(FirstPriority >= ezTaskPriority::EarlyThisFrame && LastPriority < ezTaskPriority::ENUM_COUNT,
                "Priority Range is invalid: {0} to {1}", FirstPriority, LastPriority);

  for (ezUInt32 i = FirstPriority; i <= (ezUInt32)LastPriority; ++i)
  {
    if (!s_Tasks[i].IsEmpty())
      goto foundany;
  }

  {
    TaskData td;
    td.m_pTask = nullptr;
    td.m_pBelongsToGroup = nullptr;
    return td;
  }


foundany:
  // we have detected that there MIGHT be work

  EZ_LOCK(s_TaskSystemMutex);

  // if there is a task that should be prioritized, check if it exists in any of the task lists
  if (pPrioritizeThis != nullptr)
  {
    // only search for the task in the lists that this thread is willing to work on
    // otherwise we might execute a main-thread task in a thread that is not the main thread
    for (ezUInt32 i = FirstPriority; i <= (ezUInt32)LastPriority; ++i)
    {
      auto it = s_Tasks[i].GetIterator();

      // just blindly search the entire list
      while (it.IsValid())
      {
        // if we find that task, return it
        // otherwise this whole search will do nothing and the default priority based
        // system will take over
        if (it->m_pTask == pPrioritizeThis)
        {
          TaskData td = *it;

          s_Tasks[i].Remove(it);
          return td;
        }

        ++it;
      }
    }
  }

  // go through all the task lists that this thread is willing to work on
  for (ezUInt32 i = FirstPriority; i <= (ezUInt32)LastPriority; ++i)
  {
    // if the list is not empty, just take the first task and execute that
    if (!s_Tasks[i].IsEmpty())
    {
      TaskData td = *s_Tasks[i].GetIterator();

      s_Tasks[i].Remove(s_Tasks[i].GetIterator());
      return td;
    }
  }

  {
    TaskData td;
    td.m_pTask = nullptr;
    td.m_pBelongsToGroup = nullptr;
    return td;
  }
}
Exemple #18
0
void ezWorld::UpdateFromThread()
{
  EZ_LOCK(GetWriteMarker());

  Update();
}