⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umc_default_memory_allocator.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//       Copyright (c) 2006-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_default_memory_allocator.h"
#include "ipps.h"

namespace UMC
{

  // structure to describe one memory block
  struct MemoryInfo
  {
    void *pMemory;          // allocated memory block
    size_t Size;            // allocated size
    MemID  MID;             // MID_INVALID if unused
    Ipp32s Alignment;       // requested alignment
    Ipp32s LocksCount;      // lock counter
    Ipp32s InvalidatedFlag; // set after Free()

    void Init()
    {
      pMemory = 0;
      Size = 0;
      MID = MID_INVALID;
    }
    // Released descriptor with not released memory of suitable size
    Ipp32s CanReuse(size_t s_Size, Ipp32s s_Alignment)
    {
      if(MID == MID_INVALID &&
        pMemory != 0 &&
        s_Size+(align_pointer<Ipp8u*>(pMemory, s_Alignment) - (Ipp8u*)pMemory) <= Size)
        return 1;
      return 0;

    }
    // assign memory to descriptor
    Status Alloc(size_t s_Size, Ipp32s s_Alignment)
    {
      if(!CanReuse(s_Size, s_Alignment)) { // can't reuse
        pMemory = ippsMalloc_8u(s_Size+s_Alignment);
        if(pMemory == 0) {
          vm_debug_trace1(VM_DEBUG_ERROR, VM_STRING("failed to allocate %d bytes"), (Ipp32s)Size);
          return UMC_ERR_ALLOC;
        }
        Size = s_Size+s_Alignment; // align to be done on Lock() call
      }
      Alignment = s_Alignment;
      LocksCount = 0;
      InvalidatedFlag = 0;
      return UMC_OK;
    }
    // mark as no more used checking the state
    void Clear()
    {
      if(pMemory != 0) {
        if(InvalidatedFlag == 0) {
          vm_debug_trace2(VM_DEBUG_MEMORY, VM_STRING("Mem block ID:%d size:%d wasn't released"),
            (Ipp32s)MID, (Ipp32s)Size);
          InvalidatedFlag = 1;
        }
        if(LocksCount != 0) {
          vm_debug_trace2(VM_DEBUG_MEMORY, VM_STRING("Mem block ID:%d size:%d has bad lock counter"),
            (Ipp32s)MID, (Ipp32s)Size);
          LocksCount = 0;
        }
        MID = MID_INVALID;
      }
    }
    // release memory allocated to descriptor
    void Release()
    {
      if(pMemory != 0) {
        Clear();
        ippsFree(pMemory);
        pMemory = 0;
      }

    }
  };


DefaultMemoryAllocator::DefaultMemoryAllocator(void)
{
    memInfo = 0;
    memCount = 0; // allocate only on call
    memUsed = 0;
    lastMID = MID_INVALID;
    Init(NULL);
}

DefaultMemoryAllocator::~DefaultMemoryAllocator(void)
{
    DefaultMemoryAllocator::Close();
}

Status DefaultMemoryAllocator::Init(MemoryAllocatorParams* /*pParams*/)
{
    DefaultMemoryAllocator::Close();

    return UMC_OK;
}

Status DefaultMemoryAllocator::Close()
{
  Ipp32s i;
  for(i=0; i<memUsed; i++) {
    memInfo[i].Release();
  }
  if(memInfo != 0) {
    ippsFree(memInfo);
    memInfo = 0;
  }
  memUsed = 0;
  memCount = 0;

  return UMC_OK;
}

Status DefaultMemoryAllocator::Alloc(MemID *pNewMemID, size_t Size, Ipp32u /*Flags*/, Ipp32u Align/*=16*/)
{
  Ipp32s i;
  MemoryInfo* pmem = 0;
  MemoryInfo* pmemtofree = 0;

  if (pNewMemID == NULL)
    return UMC_ERR_NULL_PTR;

  if (Size == 0 || Align == 0)
    return UMC_ERR_INVALID_PARAMS;

  *pNewMemID = MID_INVALID;


  for (i = 1; i <= (1 << 20); i <<= 1) {
    if (i & Align) {
      break; // stop at nonzero bit
    }
  }

  if (i != (Ipp32s)Align) // no 1 in 20 ls bits or more than 1 nonzero bit
    return UMC_ERR_INVALID_PARAMS;

  for (i=0; i<memUsed; i++) { // search unused or free
    if (memInfo[i].pMemory == 0 || memInfo[i].CanReuse(Size, Align)) {
      pmem = &memInfo[i];
      break;
    } else if(memInfo[i].MID == MID_INVALID)
      pmemtofree = &memInfo[i];
  }
  if (pmem == 0 && memUsed < memCount) { // take from never used
    pmem = &memInfo[memUsed];
    memUsed ++;
  }
  if(pmem == 0 && pmemtofree != 0) { // release last unsuitable
    pmemtofree->Release();
    pmem = pmemtofree;
  }
  if (pmem == 0) { // relocate all descriptors
    Ipp32s newcount = IPP_MAX(8, memCount*2);
    MemoryInfo* newmem = (MemoryInfo*)ippsMalloc_8u(newcount*sizeof(MemoryInfo));
    if (newmem == 0) {
      vm_debug_trace1(VM_DEBUG_ERROR, VM_STRING("failed to allocate %d bytes"), newcount*sizeof(MemoryInfo));
      return UMC_ERR_ALLOC;
    }

    for (i=0; i<memCount; i++) // copy existing
      newmem[i] = memInfo[i];

    // free old descriptors
    if (memInfo)
        ippsFree(memInfo);

    memInfo = newmem;
    memCount = newcount;
    for (; i<memCount; i++)
      memInfo[i].Init(); // init new

    pmem = &memInfo[memUsed]; // take first in new
    memUsed ++;
  }

  if(UMC_OK != pmem->Alloc(Size, Align))
    return UMC_ERR_ALLOC;
  lastMID++;
  pmem->MID = lastMID;
  *pNewMemID = lastMID;

  return UMC_OK;
}

void* DefaultMemoryAllocator::Lock(MemID MID)
{
  Ipp32s i;

  if( MID == MID_INVALID )
    return NULL;

  for (i=0; i<memUsed; i++) {
    if (memInfo[i].MID == MID) {
      if(memInfo[i].pMemory == 0 || memInfo[i].InvalidatedFlag)
        return NULL; // no memory or invalidated
      memInfo[i].LocksCount ++;
      // return with aligning
      return align_pointer<Ipp8u*>(memInfo[i].pMemory, memInfo[i].Alignment);
    }
  }

  return NULL;
}

Status DefaultMemoryAllocator::Unlock(MemID MID)
{
  Ipp32s i;

  if( MID == MID_INVALID )
    return UMC_ERR_FAILED;

  for (i=0; i<memUsed; i++) {
    if (memInfo[i].MID == MID) {
      if(memInfo[i].pMemory == 0 || memInfo[i].LocksCount <= 0)
        return UMC_ERR_FAILED; // no mem or lock /unlock mismatch
      memInfo[i].LocksCount --;
      if(memInfo[i].LocksCount == 0 && memInfo[i].InvalidatedFlag)
        memInfo[i].Clear(); //  no more use
      return UMC_OK;
    }
  }

  return UMC_ERR_FAILED;
}

Status DefaultMemoryAllocator::Free(MemID MID)
{
  Ipp32s i;

  if( MID == MID_INVALID )
    return UMC_ERR_FAILED;

  for (i=0; i<memUsed; i++) {
    if (memInfo[i].MID == MID) {
      if(memInfo[i].pMemory == 0 || memInfo[i].InvalidatedFlag != 0)
        return UMC_ERR_FAILED; // no mem or re-free
      memInfo[i].InvalidatedFlag = 1;
      if(memInfo[i].LocksCount == 0)
        memInfo[i].Clear(); // not in use
      return UMC_OK;
    }
  }

  return UMC_ERR_FAILED;
}

Status DefaultMemoryAllocator::DeallocateMem(MemID MID)
{
  Ipp32s i;

  if( MID == MID_INVALID )
    return UMC_ERR_FAILED;

  for (i=0; i<memUsed; i++) {
    if (memInfo[i].MID == MID) {
      if(memInfo[i].pMemory == 0)
        return UMC_ERR_FAILED; // no memory
      memInfo[i].InvalidatedFlag = 1;
      memInfo[i].Clear();
      return UMC_OK;
    }
  }

  return UMC_OK;
}

} // namespace UMC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -