ue引擎底層封裝了整套執行緒框架,下面是類圖,主要包括三部分,後文分別介紹:
執行緒庫基礎類(左上角)
執行緒池相關類(右上角)
taskgraph相關類(下半部)
ue抽象了執行緒物件和相關管理型別,沒有使用c++標準thread類。
執行緒可執行物件的基類,包含可執行物件抽象方法init、run、exit宣告。多執行緒模式時,會執行該物件的run方法。
當啟動引數包含nothreading,以單執行緒模式啟動,原先邏輯定義的執行緒執行邏輯是怎麼樣的呢?針對這個情況,引擎做了優雅設計,frunnable提供了getsinglethreadinte***ce抽象介面,單執行緒模式下,引擎會通過該介面的tick方法驅動執行緒可執行物件。
所以,執行緒標準需要分別實現run和getsinglethreadinte***ce方法,才能同時支援多執行緒和單執行緒模式。
執行緒可執行物件在單執行緒模式下,通過實現該介面的tick方法驅動。
執行緒物件基類,靜態工廠方法create建立新執行緒。建立引數包括執行緒可執行物件指標、執行緒名字、堆疊大小、執行緒優先順序、執行緒親和性(thead affinity)。多執行緒模式時,呼叫各個平台的實現介面建立出平台執行緒子類並執行,linux平台呼叫pthread_create介面建立執行緒;單執行緒模式,直接建立ffakethread(偽執行緒)物件,後續在主線程中tick中驅動。
多執行緒模式下,該物件建立後,實際是通過具體平台的執行緒介面執行frunnable物件的run方法
偽執行緒類,繼承自frunnablethread, 實現了執行緒相關介面,但是不存在平台層面的執行緒,而是需要引擎週期性通過tick驅動。單執行緒模式下,frunnablethread::create工廠方法實際建立的是ffakethread物件。
執行緒管理器,內部維護乙個執行緒id到ffakethread物件的tmap。另外還實現tick方法,驅動所有ffakethread。ffakethread在建構函式中將自己加入fthreadmanager, 在析構函式中將自身從fthreadmanager刪除。
fthreadmanager::tick方法在fengineloop::tick方法中被呼叫。
執行緒池封裝的幾個主要型別:
佇列執行緒池的可執行物件封裝,該類的工廠方法create會建立乙個執行緒物件並執行。主要和fqueuedthreadpool結合使用。
佇列執行緒池物件基類,規範了執行緒池介面。
繼承自fqueuedthreadpool,佇列執行緒池的實現類。該類維護乙個iqueuedwork任務佇列和fqueuedthread執行緒列表。
引擎初始化時,如果啟用了多執行緒模式,則會建立下面四種執行緒池。開發者可根據任務型別和希望優先順序選擇合適的執行緒池。
在fengineloop::preinit呼叫中初始化,執行緒池中工作執行緒數量有嚴格限制,dedicatedserver方式執行的話該執行緒池中只有乙個工作執行緒。執行緒優先順序tpri_slightlybelownormal(=14,優先順序範圍是1-31,31為最高優先順序),優先順序一般。
在fengineloop::preinit呼叫中初始化,在glargethreadpool初始化**後。執行緒優先順序是tpri_abovenormal(=25),算很高了。
該執行緒池主要用來處理io相關的任務,例如從大檔案中讀取資料。
在fengineloop::preinit呼叫中初始化,在gthreadpool初始化**後。執行緒池中工作執行緒數量dedicatedserver執行模式為1,其它執行模式為2。執行緒優先順序為tpri_lowest(=1),幾乎是最低優先順序。
在fengineloop::preinit呼叫中初始化,在gbackgroundprioritythreadpool初始化**後,不過有with_editor條件編譯。工作執行緒數量取決於邏輯核心數量,優先順序是tpri_normal(=15)。該執行緒池主要作用是editor做關照等大運算量的工作項,業務不使用。
執行緒池的使用方式(摘自引擎**):
class fthreadpoolcrash : public iqueuedwork
void abandon()
void dothreadedwork()
else
} while (true);
}};gthreadpool->addqueuedwork(new fthreadpoolcrash(0.100));
taskgraph是引擎封裝的任務(task)編排系統,在定義任務同時,可以指定任務的依賴關係,taskgraph會按照編排好的依賴關係執行任務。依賴關係指任務開始執行前可以指定多個依賴的前序任務,只有前序任務執行結束,本任務才會開始執行,最終,所有任務依賴關係形成一張有向無環圖。當然,任務也可以沒有前序依賴。
taskgraph子系統內部管理多個執行緒,分為兩種型別:外部執行緒(namedthrad)和內部執行緒(anythread)。外部執行緒指非taskgraph子系統內部建立的執行緒,例如遊戲主線程、渲染執行緒、音訊線程等,taskgraph可以把任務編排到這些外部執行緒執行;內部執行緒指taskgraph子系統初始化時新建立的工作執行緒,分為高、中、低(linux平台nice值分別為3、5、10)三種優先順序。
taskgraph子系統中任務基類,規範了任務生命週期中必須的幾個階段,執行過程中會校驗,定義了任務執行介面。
繼承自fbasegraphtask,帶模板類引數ttask。類成員方法createtask建立ttask物件時,可傳參prerequisties(fgrapheventarray型別)表示該ttask依賴的前序任務列表,並返回fgrapheventref。當該任務執行完成後,會試著啟動prerequisties表示的任務。引數ttask必須實現dotask方法,否則編譯報錯。
任務依賴關係工具型別,維護了依賴該event的所有fbasegraphtask列表。
繼承自frunnalbe和fsinglethreadrunnable, taskgraph系統中線程可執行物件的基類。
外部執行緒的可執行物件,內部維護任務佇列,提供介面迴圈執行佇列中的任務。
內部執行緒的可執行物件,內部維護任務佇列,提供介面迴圈執行佇列中的任務。
內部有frunnablethread和ftasktheadbase指標成員,表示執行緒物件和執行緒可執行物件。如果是外部執行緒,ftaskthreadbase指向fnamedtaskthread物件;如果是外部執行緒,ftaskthreadbase指向ftaskthreadanythread物件。
taskgraph子模組管理型別,規範管理介面。
繼承自ftaskgraphinte***ce,實現了管理介面。
引擎中有大量系統依賴於taskgraph子系統,例如:
至於taskgraph具體的使用方式,可在引擎**搜尋createtask, 有大量應用例項可供參考。
async.h/cpp及相關檔案中定義了系列函式,方便執行緒設施的使用。
templateauto async(easyncexecution execution, callabletype&& callable,
tuniquefunctioncompletioncallback = nullptr) -> tfuture(callable)())>
execution是個列舉,根據列舉值將callable分別編排到taskgraph、新建執行緒、或者執行緒池中執行。
templateauto asyncpool(fqueuedthreadpool& threadpool,
callabletype&& callable, tuniquefunctioncompletioncallback = nullptr)-> tfuture(callable)())>
callable編排到threadpool執行緒池中執行。
templateauto asyncthread(callabletype&& callable, uint32 stacksize = 0,
ethreadpriority threadpri = tpri_normal,
tuniquefunctioncompletioncallback = nullptr) -> tfuture(callable)())>
建立新執行緒執行callable。
inline void parallelfor(int32 num,
tfunctionrefbody,
bool bforcesinglethread,
bool bpumprenderingthread=false)
使用taskgraph子系統並行執行多個任務。具體使用方法可參見garbage collection模組中的應用例項(garbagecollection.cpp)。 UE4多執行緒
frunnable為我們提供了四個重要的介面 class core api frunnable virtual void exit init是對frunnable物件的初始化,它是由frunnablethread在建立執行緒物件後,進入執行緒函式的時候立即被frunnablethread呼叫的函式,...
多執行緒執行sql報錯處理
原文 參考 原因 使用了多執行緒,多執行緒共享了同乙個資料庫連線,但每個execute前沒有加上互斥鎖 方法 方法一 每個execute前加上互斥鎖 lock.acquire cursor.execute command,data lock.release 方法二 方法三 所有執行緒共用乙個連線池,...
Linux多執行緒報錯集合
在試用linux 執行緒模組時,試用pthread create 函式。編譯命令為gcc main.c o test時,會出現如下錯誤 tmp ccivh3bu.o in function main main.c text 0x81 undefined reference to pthread cr...