一般來說,當需要分配全域性惟一id時,一般都會有乙個變數來記錄當前最新的id值,比如叫index變數。
每次需要分配id時,只要簡單的自增一下index變數,然後index的值即為當前分配出去的id的值。
為了最大可能的延遲復用已經分配過的id,一般來說不會去特殊處理index變數,即每次自增index,並允許迴繞情況的發生。
但是最近碰到問題就是,我有一堆分配過的id,如何重新恢復出index的值。具體場景如下:
struct obj
每乙個obj物件都需要有乙個全域性惟一id和建立時間(createtime欄位)與其關聯,因此每new乙個obj物件就需要為其分配乙個不重複的全域性id。
obj可以被人為刪除,也會被過期刪除,因此無法保證在任何時間所有還存活著的obj物件id是連續的。這些obj物件會被定時寫入資料庫。
一旦程序被重啟,程式會從資料庫載入所有還存活著的obj物件,以便可以恢復現場,使重啟程序這一操作透明。要保證整個邏輯正確性,還必須要能正確的恢復出index變數。
那麼問題來了,而由於某種原因,index並不方便被存入資料庫中。
因此必須要根據現有的存活obj物件來恢復出在程序重啟前的index的值。
第一反應,肯定是遍歷一之後找到obj物件中最大的id即為原來的index,但是這裡有乙個陷阱就是index會迴繞,一旦index會迴繞之後,這個演算法就不正確了。
考慮這樣一種情況,程序執行了數月都沒有重啟,這時殘留的obj物件id可能就只剩下0xfffffffe,0xffffffff,0,1,3,5這些了,重啟之後採用上述演算法無法重新恢復出重啟前index的值為5.
再一看,還有乙個createtime用作參考,只要取obj物件中createtime最大的那個物件的id為index就行了。
然而,由於createtime是以秒為單位的,邏輯上無法保證1秒只建立乙個obj物件,問題再次繞回到第乙個演算法所遇到的困境。
因此,看起來,想要正確恢復出index的值就必須解決迴繞的問題。
要解決這個問題,就必須要有一種大小比較演算法,這種演算法即使在迴繞時,也能正確判斷大小。比如在0xfffffffe,0xffffffff,0,1,3,5這一堆id中,此演算法會認為5是最大值,而在3,5,7,9這一塊id中認為9才是最大值。
那麼究竟有沒有這種演算法呢?比較巧的是,還真有這種演算法。
假設有a,b,c三個32位無符號值,c=(a+b) % 4g。那麼只要b大於0且小於2g,c – a就一定大於0。不過這裡有乙個陷阱,如果a和c是無符號變數,那麼一定要將c-a的值轉換為int之後再使用。
再回到設定場景中去,雖然我們1秒可以new很多個obj物件,但是絕不可能new出2g個之多。
有了這個事實和演算法,答案就呼之欲出了,其中一種實現如下:
unsigned int id = 0;
time_t time = 0;
for (auto const &obj:objs) else if ((int)(id - obj.id) < 0)
}//now we got the final index value
ps. 在闡述這個blog之前,我曾請教了幾個人,但似乎並沒有其他更好的做法,覺得這個實現還算精巧,就做個筆記.
固定連線:
Excel中如何活用INDEX和MATCH函式
在excel中match函式可以返回指定內容所在的位置,而index又可以根據指定位置查詢到位置所對應的資料,各取其優點,我們可以返回指定位置相關聯的資料。1.match函式 返回指定內容所在的位置 match lookup value,lookup array,match type lookup ...
如何加快建index索引的時間
一 先來看一下建立索引要做哪些操作 1.把index key的data 讀到記憶體 如果data 沒在db cache 中,這時候很容易有大量的db file scatter read wait 2.對index key的data 作排序 sort area size 或者pga aggregate...
如何設定全域性字型
有時候為了統一介面中所有的 label,button uitextfield 等的字型,我們在初始化的時候就需要不斷地新增冗餘的 來設定自己的字型。uilabel label uilabel alloc init label.font uifont fontwithname myfont 如果你的介...