Exemple #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;
}
Exemple #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;
    }
  }
Exemple #3
0
/** Delete a hash table.
 * @param[in] _pstHashTable  Hash table to delete.
 * @return      orxSTATUS_SUCCESS / orxSTATUS_FAILURE
 */
orxSTATUS orxFASTCALL orxHashTable_Delete(orxHASHTABLE *_pstHashTable)
{
  /* Checks */
  orxASSERT(_pstHashTable != orxNULL);

  /* Clear hash table (unallocate cells) */
  orxHashTable_Clear(_pstHashTable);

  /* Free bank */
  orxBank_Delete(_pstHashTable->pstBank);

  /* Unallocate memory */
  orxMemory_Free(_pstHashTable);

  /* Done ! */
  return orxSTATUS_SUCCESS;
}
Exemple #4
0
/** Removes a track
 */
static orxINLINE void orxTimeLine_DeleteTrack(orxTIMELINE_TRACK *_pstTrack)
{
  /* Decreases counter */
  _pstTrack->u32RefCounter--;

  /* Not referenced? */
  if(_pstTrack->u32RefCounter == 0)
  {
    /* Has an ID? */
    if((_pstTrack->zReference != orxNULL)
    && (_pstTrack->zReference != orxSTRING_EMPTY))
    {
      /* Removes it from the table */
      orxHashTable_Remove(sstTimeLine.pstTrackTable, _pstTrack->u32ID);
    }

    /* Deletes it */
    orxMemory_Free(_pstTrack);
  }

  /* Done! */
  return;
}
Exemple #5
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;
}
Exemple #6
0
/** Event handler
 */
static orxSTATUS orxFASTCALL orxTimeLine_EventHandler(const orxEVENT *_pstEvent)
{
  orxSTATUS eResult = orxSTATUS_SUCCESS;

  /* Add or update? */
  if((_pstEvent->eID == orxRESOURCE_EVENT_ADD) || (_pstEvent->eID == orxRESOURCE_EVENT_UPDATE))
  {
    orxRESOURCE_EVENT_PAYLOAD *pstPayload;

    /* Gets payload */
    pstPayload = (orxRESOURCE_EVENT_PAYLOAD *)_pstEvent->pstPayload;

    /* Is config group? */
    if(pstPayload->u32GroupID == orxString_ToCRC(orxCONFIG_KZ_RESOURCE_GROUP))
    {
      orxHANDLE           hIterator;
      orxU64              u64Key;
      orxTIMELINE_TRACK  *pstTrack;

      /* For all tracks */
      for(hIterator = orxHashTable_GetNext(sstTimeLine.pstTrackTable, orxHANDLE_UNDEFINED, &u64Key, (void **)&pstTrack);
          hIterator != orxHANDLE_UNDEFINED;
          hIterator = orxHashTable_GetNext(sstTimeLine.pstTrackTable, hIterator, &u64Key, (void **)&pstTrack))
      {
        /* Match origin? */
        if(orxConfig_GetOriginID(pstTrack->zReference) == pstPayload->u32NameID)
        {
          orxTIMELINE        *pstTimeLine;
          orxTIMELINE_TRACK  *pstNewTrack;
          orxU32              u32Counter, u32ID, u32Flags;
          const orxSTRING     zReference;

          /* Backups counter, ID, flags & reference */
          u32Counter  = pstTrack->u32RefCounter;
          u32ID       = pstTrack->u32ID;
          u32Flags    = orxFLAG_GET(pstTrack->u32Flags, orxTIMELINE_TRACK_KU32_MASK_BACKUP);
          zReference  = pstTrack->zReference;

          /* Deletes it (but keeps it reference in the hashtable to prevent infinite loop upon table changes) */
          orxMemory_Free(pstTrack);

          /* Creates new track */
          pstNewTrack = orxTimeLine_CreateTrack(zReference);

          /* Success? */
          if(pstNewTrack != orxNULL)
          {
            /* Restores its counter */
            pstNewTrack->u32RefCounter = u32Counter;

            /* Restores its flags */
            orxFLAG_SET(pstNewTrack->u32Flags, u32Flags, orxTIMELINE_TRACK_KU32_MASK_BACKUP);
          }
          else
          {
            /* Removes old reference from the table */
            orxHashTable_Remove(sstTimeLine.pstTrackTable, u32ID);
          }

          /* For all timelines */
          for(pstTimeLine = orxTIMELINE(orxStructure_GetFirst(orxSTRUCTURE_ID_TIMELINE));
              pstTimeLine != orxNULL;
              pstTimeLine = orxTIMELINE(orxStructure_GetNext(pstTimeLine)))
          {
            orxU32 u32Index;

            /* For all its track */
            for(u32Index = 0; u32Index < orxTIMELINE_KU32_TRACK_NUMBER; u32Index++)
            {
              /* Matches? */
              if(pstTimeLine->astTrackList[u32Index].pstTrack == pstTrack)
              {
                /* Updates its data */
                pstTimeLine->astTrackList[u32Index].pstTrack = pstNewTrack;
              }
            }
          }
        }
      }
    }
  }

  /* Done! */
  return eResult;
}
Exemple #7
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;
}
Exemple #8
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;
}