Ejemplo n.º 1
0
/** Create a new hash table and return it.
 * @param[in] _u32NbKey    Number of keys that will be inserted.
 * @param[in] _u32Flags    Flags used by the hash table
 * @param[in] _eMemType    Memory type to use
 * @return Returns the hashtable pointer or orxNULL if failed.
 */
orxHASHTABLE *orxFASTCALL orxHashTable_Create(orxU32 _u32NbKey, orxU32 _u32Flags, orxMEMORY_TYPE _eMemType)
{
  orxHASHTABLE *pstHashTable;
  orxU32        u32Size;
  orxU32        u32Flags;

  /* Checks */
  orxASSERT(_eMemType < orxMEMORY_TYPE_NUMBER);
  orxASSERT(_u32NbKey > 0);

  /* Gets Power of Two size */
  u32Size = orxMath_GetNextPowerOfTwo(_u32NbKey);

  /* Allocate memory for a hash table */
  pstHashTable = (orxHASHTABLE *)orxMemory_Allocate(sizeof(orxHASHTABLE) + (u32Size * sizeof(orxHASHTABLE_CELL *)), _eMemType);

  /* Enough memory ? */
  if(pstHashTable != orxNULL)
  {
    /* Set flags */
    if(_u32Flags == orxHASHTABLE_KU32_FLAG_NOT_EXPANDABLE)
    {
      u32Flags = orxBANK_KU32_FLAG_NOT_EXPANDABLE;
    }
    else
    {
      u32Flags = orxBANK_KU32_FLAG_NONE;
    }

    /* Clean values */
    orxMemory_Zero(pstHashTable, sizeof(orxHASHTABLE) + (u32Size * sizeof(orxHASHTABLE_CELL *)));

    /* Allocate bank for cells */
    pstHashTable->pstBank = orxBank_Create((orxU16)u32Size, sizeof(orxHASHTABLE_CELL), u32Flags, _eMemType);

    /* Correct bank allocation ? */
    if(pstHashTable->pstBank != orxNULL)
    {
      /* Stores its size */
      pstHashTable->u32Size = u32Size;
    }
    else
    {
      /* Allocation problem, returns orxNULL */
      orxMemory_Free(pstHashTable);
      pstHashTable = orxNULL;
    }
  }

  return pstHashTable;
}
Ejemplo n.º 2
0
/** Create a new bank in memory and returns a pointer on it
 * @param[in] _u16NbElem  Number of elements per segments
 * @param[in] _u32Size    Size of an element
 * @param[in] _u32Flags   Flags set for this bank
 * @param[in] _eMemType   Memory type where the Data will be allocated
 * @return  returns a pointer on the memory bank
 */
orxBANK *orxFASTCALL orxBank_Create(orxU16 _u16NbElem, orxU32 _u32Size, orxU32 _u32Flags, orxMEMORY_TYPE _eMemType)
{
  orxBANK *pstBank;

  /* Module initialized ? */
  orxASSERT((sstBank.u32Flags & orxBANK_KU32_STATIC_FLAG_READY) == orxBANK_KU32_STATIC_FLAG_READY);

  /* Correct parameters ? */
  orxASSERT(_eMemType < orxMEMORY_TYPE_NUMBER);
  orxASSERT(_u16NbElem > 0);
  orxASSERT(_u32Size > 0);

  /* Allocate the bank */
  pstBank = (orxBANK *)orxMemory_Allocate(sizeof(orxBANK), _eMemType);

  /* Memory allocated ? */
  if(pstBank != orxNULL)
  {
    /* Set initial values */
    orxMemory_Zero(pstBank, sizeof(orxBANK));
    pstBank->u32Counter               = 0;
    pstBank->u32ElemSize              = (_u32Size > sstBank.u32CacheLineSize)
                                        ? (orxU32)orxALIGN(_u32Size, sstBank.u32CacheLineSize)
                                        : (orxMath_IsPowerOfTwo(_u32Size) == orxFALSE)
                                          ? orxMath_GetNextPowerOfTwo(_u32Size)
                                          : _u32Size;
    pstBank->u32Flags                 = _u32Flags;
    pstBank->u16NbCellPerSegments     = _u16NbElem;
    pstBank->eMemType                 = _eMemType;

    /* Compute the necessary number of 32 bits packs */
    pstBank->u16SizeSegmentBitField   = orxALIGN32(_u16NbElem) >> 5;

    /* Allocate the first segment, and select it as current */
    pstBank->pstFirstSegment          = orxBank_CreateSegment(pstBank);

    /* Success? */
    if(pstBank->pstFirstSegment != orxNULL)
    {
      /* Add it to the list */
      orxLinkList_AddEnd(&(sstBank.stBankList), &(pstBank->stNode));
    }
    else
    {
      /* Can't allocate segment, cancel bank allocation */
      orxMemory_Free(pstBank);
      pstBank = orxNULL;
    }
  }
Ejemplo n.º 3
0
/** Create a new segment of memory and returns a pointer on it
 * @param[in] _pstBank    Concerned bank
 * @return  returns a pointer on the memory segment (orxNULL if an error occurred)
 */
static orxINLINE orxBANK_SEGMENT *orxBank_CreateSegment(const orxBANK *_pstBank)
{
  orxBANK_SEGMENT *pstSegment;  /* Pointer on the segment of memory */
  orxU32 u32BaseSegmentSize;    /* Base size of segment allocation */

  /* Profiles */
  orxPROFILER_PUSH_MARKER("orxBank_CreateSegment");

  /* Module initialized ? */
  orxASSERT((sstBank.u32Flags & orxBANK_KU32_STATIC_FLAG_READY) == orxBANK_KU32_STATIC_FLAG_READY);

  /* Correct parameters ? */
  orxASSERT(_pstBank != orxNULL);

  /* Compute the base segment size */
  u32BaseSegmentSize = sizeof(orxBANK_SEGMENT) + _pstBank->u16SizeSegmentBitField * sizeof(orxU32);

  /* Allocates a new segment of memory */
  pstSegment = (orxBANK_SEGMENT *)orxMemory_Allocate(u32BaseSegmentSize + sstBank.u32CacheLineSize - 1 + (_pstBank->u16NbCellPerSegments * _pstBank->u32ElemSize), _pstBank->eMemType);
  if(pstSegment != orxNULL)
  {
    orxU8 *pAlignedSegmentData;

    /* Set initial segment values */
    orxMemory_Zero(pstSegment, u32BaseSegmentSize + (_pstBank->u16NbCellPerSegments * _pstBank->u32ElemSize));
    pstSegment->pstNext               = orxNULL;
    pstSegment->u32NbFree             = _pstBank->u16NbCellPerSegments;
    pAlignedSegmentData               = ((orxU8 *)pstSegment) + u32BaseSegmentSize;
    pstSegment->pSegmentData          = (void *)orxALIGN(pAlignedSegmentData, sstBank.u32CacheLineSize);
  }

  /* Profiles */
  orxPROFILER_POP_MARKER();

  /* Done! */
  return pstSegment;
}
Ejemplo n.º 4
0
static orxINLINE orxU32 orxMemory_CacheLineSize()
{
  SYSTEM_LOGICAL_PROCESSOR_INFORMATION *astProcessorInfoList;
  orxU32                                u32InfoListSize = 0, u32Result = orxMEMORY_KU32_DEFAULT_CACHE_LINE_SIZE, i, u32Number;

  /* Requests total size of processors info */
  GetLogicalProcessorInformation(0, (PDWORD)&u32InfoListSize);

  /* Allocates info list */
  astProcessorInfoList = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)orxMemory_Allocate(u32InfoListSize, orxMEMORY_TYPE_TEMP);

  /* Gets processors info */
  GetLogicalProcessorInformation(astProcessorInfoList, (PDWORD)&u32InfoListSize);

  /* For all processor info */
  for(i = 0, u32Number = u32InfoListSize / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
      i < u32Number;
      i++)
  {
    /* Found first level cache info? */
    if((astProcessorInfoList[i].Relationship == RelationCache)
    && (astProcessorInfoList[i].Cache.Level == 1))
    {
      /* Updates result */
      u32Result = astProcessorInfoList[i].Cache.LineSize;

      break;
    }
  }

  /* Frees info list */
  orxMemory_Free(astProcessorInfoList);

  /* Done! */
  return u32Result;
}
Ejemplo n.º 5
0
static void Run()
{
  // Ready?
  if(orxFLAG_TEST_ALL(sstFontGen.u32Flags, orxFONTGEN_KU32_STATIC_MASK_READY))
  {
    orxU32 u32Counter;

    // Gets glyph list's counter
    u32Counter = orxLinkList_GetCounter(&sstFontGen.stGlyphList);

    // Valid?
    if(u32Counter)
    {
      orxS32      s32Width, s32Height, s32BaseLine, s32MaxAscend, s32MaxDescend;
      orxSTRING  *azWidthList = orxNULL;
      orxFLOAT    fWidth, fHeight;
      orxU8      *pu8ImageBuffer;

      // Not monospaced?
      if(!orxFLAG_TEST(sstFontGen.u32Flags, orxFONTGEN_KU32_STATIC_FLAG_MONOSPACE))
      {
        orxU32 i;

        // Allocates width list
        azWidthList = (orxSTRING *)orxMemory_Allocate(u32Counter * sizeof(orxSTRING), orxMEMORY_TYPE_MAIN);

        // Checks
        orxASSERT(azWidthList);

        // For all strings
        for(i = 0; i < u32Counter; i++)
        {
          azWidthList[i] = (orxSTRING)orxMemory_Allocate(8 * sizeof(orxCHAR), orxMEMORY_TYPE_MAIN);
        }
      }

      // No font name?
      if(!sstFontGen.zFontName)
      {
        // Uses default one
        sstFontGen.zFontName = orxString_Duplicate(orxFONTGEN_KZ_DEFAULT_NAME);

        // Logs message
        orxFONTGEN_LOG(OUTPUT, "No output name specified, defaulting to '%s'.", orxFONTGEN_KZ_DEFAULT_NAME);
      }

      // Is not monospaced?
      if(!orxFLAG_TEST(sstFontGen.u32Flags, orxFONTGEN_KU32_STATIC_FLAG_MONOSPACE))
      {
        orxFONTGEN_GLYPH *pstGlyph;
        orxS32            s32LargestWidth = 0;

        // For all defined glyphs
        for(pstGlyph = (orxFONTGEN_GLYPH *)orxLinkList_GetFirst(&sstFontGen.stGlyphList);
            pstGlyph;
            pstGlyph = (orxFONTGEN_GLYPH *)orxLinkList_GetNext(&pstGlyph->stNode))
        {
          orxS32    s32CharacterWidth;
          FT_Error  eError;

          // Loads rendered glyph
          eError = FT_Load_Glyph(sstFontGen.pstFontFace, (FT_UInt)pstGlyph->u32Index, FT_LOAD_RENDER);
          orxASSERT(!eError);

          // Use original advance value?
          if(orxFLAG_TEST(sstFontGen.u32Flags, orxFONTGEN_KU32_STATIC_FLAG_ADVANCE))
          {
            // Gets character width
            s32CharacterWidth = sstFontGen.pstFontFace->glyph->advance.x >> 6;
          }
          else
          {
            // Gets character width
            s32CharacterWidth = orxMAX((orxS32)sstFontGen.pstFontFace->glyph->bitmap_left, 0) + (orxS32)sstFontGen.pstFontFace->glyph->bitmap.width;
          }

          // Updates largest character width
          s32LargestWidth = orxMAX(s32LargestWidth, s32CharacterWidth);
        }
Ejemplo n.º 6
0
/** Adds a track
 */
static orxINLINE orxTIMELINE_TRACK *orxTimeLine_CreateTrack(const orxSTRING _zTrackID)
{
  orxTIMELINE_TRACK *pstResult = orxNULL;

  /* Pushes section */
  if((orxConfig_HasSection(_zTrackID) != orxFALSE)
  && (orxConfig_PushSection(_zTrackID) != orxSTATUS_FAILURE))
  {
    orxU32 u32KeyCounter;

    /* Gets number of keys */
    u32KeyCounter = orxConfig_GetKeyCounter();

    /* Valid? */
    if(u32KeyCounter > 0)
    {
      orxU32 u32EventCounter = 0, i;

#ifdef __orxMSVC__

      orxFLOAT *afTimeList = (orxFLOAT *)alloca(u32KeyCounter * sizeof(orxFLOAT));

#else /* __orxMSVC__ */

      orxFLOAT afTimeList[u32KeyCounter];

#endif /* __orxMSVC__ */

      /* For all time entries */
      for(i = 0; i < u32KeyCounter; i++)
      {
        /* Inits it */
        afTimeList[i] = orxFLOAT_MAX;
      }

      /* For all config keys */
      for(i = 0; i < u32KeyCounter; i++)
      {
        const orxSTRING zKey;
        orxFLOAT        fTime;

        /* Gets it */
        zKey = orxConfig_GetKey(i);

        /* Is a valid time stamp? */
        if((orxString_ToFloat(zKey, &fTime, orxNULL) != orxSTATUS_FAILURE)
        && (fTime >= orxFLOAT_0))
        {
          /* Stores it */
          afTimeList[i] = fTime;

          /* Updates event counter */
          u32EventCounter += orxConfig_GetListCounter(zKey);
        }
        else
        {
          /* Not keep in cache, immediate nor loop? */
          if((orxString_Compare(orxTIMELINE_KZ_CONFIG_KEEP_IN_CACHE, zKey) != 0)
          && (orxString_Compare(orxTIMELINE_KZ_CONFIG_IMMEDIATE, zKey) != 0)
          && (orxString_Compare(orxTIMELINE_KZ_CONFIG_LOOP, zKey) != 0))
          {
            /* Logs message */
            orxDEBUG_PRINT(orxDEBUG_LEVEL_OBJECT, "TimeLine track [%s]: ignoring invalid key (%s).", _zTrackID, zKey);
          }
        }
      }

      /* Allocates track */
      pstResult = (orxTIMELINE_TRACK *)orxMemory_Allocate(sizeof(orxTIMELINE_TRACK) + (u32EventCounter * sizeof(orxTIMELINE_TRACK_EVENT)), orxMEMORY_TYPE_MAIN);

      /* Valid? */
      if(pstResult != orxNULL)
      {
        /* Stores its ID */
        pstResult->u32ID = orxString_GetID(orxConfig_GetCurrentSection());

        /* Adds it to reference table */
        if(orxHashTable_Set(sstTimeLine.pstTrackTable, pstResult->u32ID, pstResult) != orxSTATUS_FAILURE)
        {
          orxU32 u32EventIndex, u32Flags = orxTIMELINE_TRACK_KU32_FLAG_NONE;

          /* For all events */
          for(u32EventIndex = 0; u32EventIndex < u32EventCounter;)
          {
            const orxSTRING zKey;
            orxFLOAT        fTime;
            orxU32          u32KeyIndex, u32ListCounter;

            /* Finds time to add next */
            for(fTime = orxFLOAT_MAX, u32KeyIndex = orxU32_UNDEFINED, i = 0; i < u32KeyCounter; i++)
            {
              /* Is sooner? */
              if(afTimeList[i] < fTime)
              {
                /* Stores it */
                fTime       = afTimeList[i];
                u32KeyIndex = i;
              }
            }

            /* Checks */
            orxASSERT(u32KeyIndex != orxU32_UNDEFINED);

            /* Gets corresponding key */
            zKey = orxConfig_GetKey(u32KeyIndex);

            /* For all events */
            for(i = 0, u32ListCounter = orxConfig_GetListCounter(zKey);
                i < u32ListCounter;
                i++, u32EventIndex++)
            {
              /* Checks */
              orxASSERT(u32EventIndex < u32EventCounter);

              /* Stores event */
              pstResult->astEventList[u32EventIndex].fTimeStamp = fTime;
              pstResult->astEventList[u32EventIndex].zEventText = orxString_Store(orxConfig_GetListString(zKey, i));
            }

            /* Clears time entry */
            afTimeList[u32KeyIndex] = orxFLOAT_MAX;
          }

          /* Stores its reference */
          pstResult->zReference = orxString_GetFromID(pstResult->u32ID);

          /* Updates track counters */
          pstResult->u32RefCounter    = 1;
          pstResult->u32EventCounter  = u32EventCounter;

          /* Should keep in cache? */
          if(orxConfig_GetBool(orxTIMELINE_KZ_CONFIG_KEEP_IN_CACHE) != orxFALSE)
          {
            /* Increases its reference counter to keep it in cache table */
            pstResult->u32RefCounter++;

            /* Updates flags */
            u32Flags |= orxTIMELINE_TRACK_KU32_FLAG_CACHED;
          }

          /* Should loop? */
          if(orxConfig_GetBool(orxTIMELINE_KZ_CONFIG_LOOP) != orxFALSE)
          {
            /* Updates flags */
            u32Flags |= orxTIMELINE_TRACK_KU32_FLAG_LOOP;
          }

          /* Is immediate? */
          if(orxConfig_GetBool(orxTIMELINE_KZ_CONFIG_IMMEDIATE) != orxFALSE)
          {
            /* Updates flags */
            u32Flags |= orxTIMELINE_TRACK_KU32_FLAG_IMMEDIATE;
          }

          /* Stores flags */
          pstResult->u32Flags = u32Flags;
        }
        else
        {
          /* Logs message */
          orxDEBUG_PRINT(orxDEBUG_LEVEL_OBJECT, "Failed to add track to hashtable.");

          /* Deletes it */
          orxMemory_Free(pstResult);

          /* Updates result */
          pstResult = orxNULL;
        }
      }
      else
      {
        /* Logs message */
        orxDEBUG_PRINT(orxDEBUG_LEVEL_OBJECT, "Couldn't create TimeLine track [%s]: memory allocation failure.", _zTrackID);
      }
    }
    else
    {
      /* Logs message */
      orxDEBUG_PRINT(orxDEBUG_LEVEL_OBJECT, "Couldn't create TimeLine track [%s]: config section is empty.", _zTrackID);
    }

    /* Pops previous section */
    orxConfig_PopSection();
  }
  else
  {
    /* Logs message */
    orxDEBUG_PRINT(orxDEBUG_LEVEL_OBJECT, "Couldn't create TimeLine track [%s]: config section not found.", _zTrackID);
  }

  /* Done! */
  return pstResult;
}
Ejemplo n.º 7
0
/** Optimizes a hashtable for read accesses (minimizes number of cache misses upon collisions)
 * @param[in] _pstHashTable HashTable to optimize
 * @return orxSTATUS_SUCESS / orxSTATUS_FAILURE
 */
orxSTATUS orxFASTCALL orxHashTable_Optimize(orxHASHTABLE *_pstHashTable)
{
  orxSTATUS eResult = orxSTATUS_SUCCESS;

  /* Checks */
  orxASSERT(_pstHashTable != orxNULL);

  /* Has elements? */
  if(_pstHashTable->u32Counter > 0)
  {
    orxHASHTABLE_CELL *astWorkBuffer;

    /* Allocates work buffer */
    astWorkBuffer = (orxHASHTABLE_CELL *)orxMemory_Allocate(_pstHashTable->u32Counter * sizeof(orxHASHTABLE_CELL), orxMEMORY_TYPE_TEMP);

    /* Valid? */
    if(astWorkBuffer != orxNULL)
    {
      orxU64              u64KeyIndex;
      orxU32              u32BufferIndex, i;
      orxHASHTABLE_CELL  *pstCell;

      /* For all cells */
      for(i = 0, u64KeyIndex = 0, u32BufferIndex = 0, pstCell = orxNULL; i < _pstHashTable->u32Counter; i++, u32BufferIndex++)
      {
        /* Linked cell? */
        if((pstCell != orxNULL) && (pstCell->pstNext != orxNULL))
        {
          /* Gets next in line */
          pstCell = pstCell->pstNext;
        }
        else
        {
          /* Finds next head cell */
          do{pstCell = _pstHashTable->apstCell[u64KeyIndex++];} while(pstCell == orxNULL);
        }

        /* Stores it */
        orxMemory_Copy(&astWorkBuffer[u32BufferIndex], pstCell, sizeof(orxHASHTABLE_CELL));
      }

      /* Clears bank */
      orxBank_Clear(_pstHashTable->pstBank);

      /* For all ordered cells */
      for(i = 0, pstCell = orxNULL; i < _pstHashTable->u32Counter; i++)
      {
        orxHASHTABLE_CELL *pstPreviousCell;

        /* Allocates new cell */
        pstPreviousCell = pstCell;
        pstCell         = (orxHASHTABLE_CELL *)orxBank_Allocate(_pstHashTable->pstBank);

        /* Checks */
        orxASSERT(pstCell != orxNULL);

        /* Stores its data */
        orxMemory_Copy(pstCell, &astWorkBuffer[i], sizeof(orxHASHTABLE_CELL));

        /* Chained? */
        if((pstPreviousCell != orxNULL) && (pstPreviousCell->pstNext != orxNULL))
        {
          /* Updates chaining */
          pstPreviousCell->pstNext = pstCell;
        }
        else
        {
          /* Updates head pointer */
          _pstHashTable->apstCell[orxHashTable_FindIndex(_pstHashTable, pstCell->u64Key)] = pstCell;
        }
      }

      /* Clears work buffer */
      orxMemory_Free(astWorkBuffer);
    }
    else
    {
      /* Updates result */
      eResult = orxSTATUS_FAILURE;
    }
  }

  /* Done! */
  return eResult;
}