Domanda

Volevo un numero che sarebbe rimasto unico per un giorno (24 ore). Di seguito è riportato il codice che mi si avvicinò con; Mi chiedevo sui suoi Inganni / possibili rischi; 'Credo' questo garantisce un numero univoco di 12 cifre per un giorno atleast.

Logic è per ottenere la data / ora corrente (hhmmssmmm) e concat i primi quattro byte di risulta contatore delle prestazioni di query.

__forceinline bool GetUniqueID(char caUID[MAX_STRING_LENGTH])
{
    //Logic: Add HHMMSSmmm with mid 3 bytes of performance counter.
    //Guarantees that in a single milli second band (0 to 999) the three bytes 
    //of performance counter would always be unique.
    //1. Get system time, and use
    bool bStatus = false;
    try
    {

        SYSTEMTIME localtime;
        GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm

        LARGE_INTEGER li;
        char cNT[MAX_STRING_LENGTH];//new time.
        memset(cNT, '\0', sizeof(cNT));
        try
        {
            //Try to get the performance counter,
            //if one is provided by the OEM.

            QueryPerformanceCounter(&li);//This function retrieves the current value of the 
                                         //high-resolution performance counter if one is provided by the OEM
                                         //We use the first four bytes only of it.
            sprintf(cNT, "%u", li.QuadPart);
        }
        catch(...)
        {
            //Not provided by OEM.
            //Lets go with the GetTickCounts();
            //ddHHMMSS + 4 bytes of dwTicks
            sprintf(cNT,"%04d", GetTickCount());
        }


        //Get the first four bytes.
        int iSkipTo     = 0;//This is incase we'd decide to pull out next four bytes, rather than first four bytes.
        int iGetChars   = 4;//Number of chars to get.
        char *pSub = (char*) malloc(iGetChars+1);//Clear memory
        strncpy(pSub, cNT + iSkipTo, iGetChars);//Get string
        pSub[iGetChars] = '\0'; //Mark end.

        //Prepare unique id
        sprintf(caUID, "%02d%02d%02d%3d%s", 
                                    localtime.wHour, 
                                    localtime.wMinute, 
                                    localtime.wSecond, 
                                    localtime.wMilliseconds, 
                                    pSub); //First four characters concat.

        bStatus = true;
    }
    catch(...)
    {
        //Couldnt prepare. There was some problem.
        bStatus = false;
    }

    return bStatus;
}

Ecco l'output che ottengo:

Unico: [125907 462224] Unico: [125907 462225] Unico: [125907 462226] Unico: [125907 462227] Unico: [125907 462228] Unico: [125907 462230] Unico: [125907 462231] Unico: [125907 462232] Unico: [125907 462233] Unico: [125907 462234] Unico: [125907 462235] Unico: [125907 462237] Unico: [125907 462238] Unico: [125907 462239] Unico: [125907 462240] Unico: [125907 462241] Unico: [125907 462243] Unico: [125907 462244] Unico: [125907 462245] Unico: [125907 462246] Unico: [125907 462247] Unico: [125907 462248] Unico: [125907 462249] Unico: [125907 462251] Unico: [125907 462252] Unico: [125907 462253] Unico: [125907 462254] Unico: [125907 462255] Unico: [125907 462256] Unico: [125907 462257] Unico: [125907 462258] Millisecondo cambiato, 46 Unico: [125907 622261] Unico: [125907 622262] Unico: [125907 622263] Unico: [125907 622264] Unico: [125907 622265] Unico: [125907 622267] Unico: [125907 622268] Unico: [125907 622269] Unico: [125907 622270] Unico: [125907 622271] Unico: [125907 622273] Unico: [125907 622274] Unico: [125907 622275] Unico: [125907 622276] Unico: [125907 622277] Unico: [125907 622278] Unico: [125907 622279] Unico: [125907 622281] Unico: [125907 622282] Unico: [125907 622283] Unico: [125907 622284] Unico: [125907 622285] Unico: [125907 622286] Unico: [125907 622288] Unico: [125907 622289] Unico: [125907 622290] Unico: [125907 622291] Unico: [125907 622292] Unico: [125907 622293] Unico: [125907 622295] Unico: [125907 622296] Unico: [125907 622297] Unico: [125907 622298] Unico: [125907 622299] Unico: [125907 622300] Unico: [125907 622301] Unico: [125907 622302] Unico: [125907 622304] Unico: [125907 622305] Unico: [125907 622306] Millisecondo cambiato, 62 Unico: [125907 782308] Unico: [125907 782310] Unico: [125907 782311] Unico: [125907 782312] Unico: [125907 782313] Unico: [125907 782314] Unico: [125907 782316] Unico: [125907 782317] Unico: [125907 782318] Unico: [125907 782319] Millisecondo cambiato, 125 Unico: [1259071402495] Unico: [1259071402497] Unico: [1259071402498] Unico: [1259071402499] Unico: [1259071402500] Unico: [1259071402502] Unico: [1259071402503] Unico: [1259071402504] Unico: [1259071402505] Unico: [1259071402507]

Ora sto pensando di mantenere gli ID generati in un elenco, e confrontare il nuovo generato uno con quelli esistenti nella lista. Se già si esiste nella lista, allora beh posso certamente saltare il numero e genera un altro, ma di certo e chiaramente questa logica fallirebbe.

Gradirei i tuoi commenti / suggerimenti / aggiornamenti / etc.

Grazie JT.

È stato utile?

Soluzione

La mia soluzione era quella di ottenere il tempo di sistema e aggiungere un contatore a quello (pseudo codice):

static int counter = 0;
static Time lastTime;

String getNextId() {
    Time now = System.getTime();
    if (lastTime == now)
        counter ++;
    else
        counter = 0;
    return now+counter;
}

Ciò garantirebbe che mi piacerebbe avere un nuovo ID, anche quando ho chiamato il metodo più spesso di cambiamenti getTime().

Altri suggerimenti

La logica sembra il suono a me, se si sta eseguendo da una macchina su un processore single-core. Non so se lo stesso vale per un processore multi-core per chiamate successive, tuttavia. I numeri generati sicuramente non essere unico tra macchine, tuttavia.

Per curiosità, c'è una ragione non si sta usando GUID?

In alternativa dal momento che si stanno prendendo in considerazione mantenendo gli ID generati in un elenco per confrontare, perché non si può creare un generatore? Dal momento che lei suggerisce di archiviazione è un'opzione, se si memorizza l'ultimo numero e incrementarlo ogni uso ... È anche possibile memorizzare la data e azzerare il contatore ogni giorno se lo si desidera.

Ho avuto problemi con i tempi nei cicli veloci dove non sono cambiate, nonostante che sia il buon senso dovrebbero (non si ha il controllo del sistema operativo in modo non si può assumere che il tempo cambia ogni x millisecondi, ecc.)

L'aggiunta del valore del contatore come un extra poche cifre (non come un incremento) e resettarlo al riavvio o dopo il 9999 dovrebbe nascondere questo basta per rendere il tutto ma impossibile che accada (le ultime parole famose).

formato è quindi TTTTTToooo dove T è la tua figura tempo e compensato o la vostra a 4 cifre.

Aaron: Grazie per i vostri commenti, ho usato il tuo approccio per ottenere quello che volevo.

__forceinline bool GetUniqueIDEx(char caUID[MAX_STRING_LENGTH])
{
    //Logic: Add HHMMSSmmm with 3 bytes counter.
    //Guarantees a unique number for a calendar date, 
    //that in a single milli second band (0 to 999) the three bytes 
    //of counter would always be unique.
    //1. Get system time, and use

    bool bStatus = false;
    try
    {
        GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm

        char cNT[MAX_STRING_LENGTH];//new time.
        memset(cNT, '\0', sizeof(cNT));
        if(m_nCounter> MAX_COUNTER_LIMIT)
        {
            m_nCounter= 0;
        }

        sprintf(cNT, "%03d", ++m_nCounter);

        //Prepare unique id
        sprintf(caUID, "%02d%02d%02d%03d%s", 
                                            localtime.wHour, 
                                            localtime.wMinute, 
                                            localtime.wSecond, 
                                            localtime.wMilliseconds, 
                                            cNT); 

        bStatus = true;
    }
    catch(...)
    {
        //Couldnt prepare. There was some problem.
        bStatus = false;
    }

    return bStatus;
}

Vorrei usare secondi dalla mezzanotte e poi un contatore. Questo ti dà fino a dieci milioni di visite per secondo. Dovrebbe essere abbastanza unico. Utilizzando il codice di Aaron sopra, si formatta la stringa come:

sprintf(idstr, "%05d%07d", secs_since_midnight, counter);

Naturalmente, Sono anche un convinto sostenitore con base-36 (via itoa) quando si vuole veramente di stipare un contatore in un paio di caratteri stampabili (e giorno dell'anno, piuttosto che il mese / giorno, ecc.)

Non sono sicuro se il processo può sacrificare piccolo problema di prestazioni e mantenere la semplice logica.

possiamo garantire il numero unico, con formato HHMMSSmmm se stessa se si mette il processo per dormire per 1 millisecondo tra due chiamate. In questo modo è possibile eliminare la parte di concatenazione e anche la lista è necessario mantenere raddoppiare controllare l'unicità.

Manikanthan Velayutham // programmato di pensare in grande

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top