EBus.cpp 154 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/EBus/EBus.h>
  9. #include <AzCore/EBus/Results.h>
  10. #include <AzCore/std/sort.h>
  11. #include <AzCore/std/chrono/chrono.h>
  12. #include <AzCore/std/parallel/mutex.h>
  13. #include <AzCore/std/parallel/thread.h>
  14. #include <AzCore/std/smart_ptr/unique_ptr.h>
  15. #include <AzCore/Jobs/JobManager.h>
  16. #include <AzCore/Jobs/JobContext.h>
  17. #include <AzCore/Jobs/JobCompletion.h>
  18. #include <AzCore/Jobs/JobFunction.h>
  19. #include <AzCore/Math/Random.h>
  20. #include <AzCore/UnitTest/TestTypes.h>
  21. #include <Tests/AZTestShared/Utils/Utils.h>
  22. #include <gtest/gtest.h>
  23. // For GetTypeName<T>()
  24. #include <gtest/internal/gtest-type-util.h>
  25. using namespace AZ;
  26. // TestBus implementation details
  27. namespace BusImplementation
  28. {
  29. // Interface for the benchmark bus
  30. class Interface
  31. {
  32. public:
  33. virtual ~Interface() = default;
  34. virtual int OnEvent() = 0;
  35. virtual void OnWait() = 0;
  36. virtual void Release() = 0;
  37. virtual bool Compare(const Interface* other) const = 0;
  38. };
  39. // Traits for the benchmark bus
  40. template <AZ::EBusAddressPolicy addressPolicy, AZ::EBusHandlerPolicy handlerPolicy, bool locklessDispatch = false>
  41. class Traits
  42. : public AZ::EBusTraits
  43. {
  44. public:
  45. static const AZ::EBusAddressPolicy AddressPolicy = addressPolicy;
  46. static const AZ::EBusHandlerPolicy HandlerPolicy = handlerPolicy;
  47. static const bool LocklessDispatch = locklessDispatch;
  48. // Allow queuing
  49. static const bool EnableEventQueue = true;
  50. // Force locking
  51. using MutexType = AZStd::recursive_mutex;
  52. // Only specialize BusIdType if not single address
  53. using BusIdType = AZStd::conditional_t<AddressPolicy == AZ::EBusAddressPolicy::Single, AZ::NullBusId, int>;
  54. // Only specialize BusIdOrderCompare if addresses are multiple and ordered
  55. using BusIdOrderCompare = AZStd::conditional_t<AddressPolicy != EBusAddressPolicy::ByIdAndOrdered, AZ::NullBusIdCompare, AZStd::less<int>>;
  56. };
  57. template <typename Bus>
  58. class HandlerCommon
  59. : public Bus::Handler
  60. {
  61. public:
  62. AZ_CLASS_ALLOCATOR(HandlerCommon, AZ::SystemAllocator);
  63. unsigned int m_eventCalls = 0;
  64. unsigned int m_expectedOrder = 0;
  65. unsigned int m_executedOrder = 0;
  66. HandlerCommon()
  67. {
  68. AZ::BetterPseudoRandom random;
  69. random.GetRandom(m_expectedOrder);
  70. }
  71. HandlerCommon(uint32_t handlerOrder)
  72. {
  73. m_expectedOrder = handlerOrder;
  74. }
  75. ~HandlerCommon() override
  76. {
  77. Bus::Handler::BusDisconnect();
  78. }
  79. bool Compare(const Interface* other) const override
  80. {
  81. return m_expectedOrder < reinterpret_cast<const HandlerCommon*>(other)->m_expectedOrder;
  82. }
  83. int OnEvent() override
  84. {
  85. ++m_eventCalls;
  86. m_executedOrder = s_nextExecution++;
  87. return 0;
  88. }
  89. void OnWait() override
  90. {
  91. AZStd::this_thread::yield();
  92. }
  93. void Release() override
  94. {
  95. delete this;
  96. }
  97. private:
  98. static int s_nextExecution;
  99. };
  100. template <typename Bus>
  101. int HandlerCommon<Bus>::s_nextExecution = 0;
  102. template <typename Bus>
  103. class MultiHandlerCommon
  104. : public Bus::MultiHandler
  105. {
  106. public:
  107. AZ_CLASS_ALLOCATOR(MultiHandlerCommon, AZ::SystemAllocator);
  108. MultiHandlerCommon() = default;
  109. ~MultiHandlerCommon() override
  110. {
  111. Bus::MultiHandler::BusDisconnect();
  112. }
  113. int OnEvent() override
  114. {
  115. ++m_eventCalls;
  116. return 0;
  117. }
  118. void OnWait() override
  119. {
  120. AZStd::this_thread::yield();
  121. }
  122. void Release() override
  123. {
  124. delete this;
  125. }
  126. bool Compare(const Interface* other) const override
  127. {
  128. return m_expectedOrder < static_cast<const MultiHandlerCommon*>(other)->m_expectedOrder;
  129. }
  130. private:
  131. uint32_t m_eventCalls{};
  132. uint32_t m_expectedOrder{};
  133. };
  134. class InterfaceWithMutex
  135. : public AZ::EBusTraits
  136. {
  137. public:
  138. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  139. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
  140. using BusIdType = uint32_t;
  141. // Setting the MutexType to a value other than NullMutex
  142. // signals to the EBus system that the Ebus is able to be used in multiple threads
  143. // and therefore the EBus must be disconnected prior to the EBus internal handler destructor being invoked
  144. using MutexType = AZStd::recursive_mutex;
  145. virtual void OnEvent() = 0;
  146. };
  147. using InterfaceWithMutexBus = AZ::EBus<InterfaceWithMutex>;
  148. }
  149. class MutexBusHandler
  150. : public BusImplementation::InterfaceWithMutexBus::Handler
  151. {
  152. void OnEvent() override
  153. {
  154. ++m_eventCalls;
  155. }
  156. private:
  157. uint32_t m_eventCalls{};
  158. };
  159. // Definition of the benchmark bus, depending on supplied policies
  160. template <AZ::EBusAddressPolicy addressPolicy, AZ::EBusHandlerPolicy handlerPolicy, bool locklessDispatch = false>
  161. using TestBus = AZ::EBus<BusImplementation::Interface, BusImplementation::Traits<addressPolicy, handlerPolicy, locklessDispatch>>;
  162. #define EBUS_TEST_ALIAS(BusType, AddressPolicy, HandlerPolicy) \
  163. using BusType = TestBus<AZ::EBusAddressPolicy::AddressPolicy, AZ::EBusHandlerPolicy::HandlerPolicy>; \
  164. namespace testing { namespace internal { template<> std::string GetTypeName<BusType>() { return #BusType; } } }
  165. // Predefined benchmark bus instantiations
  166. // Single
  167. EBUS_TEST_ALIAS(OneToOne, Single, Single)
  168. EBUS_TEST_ALIAS(OneToMany, Single, Multiple)
  169. EBUS_TEST_ALIAS(OneToManyOrdered, Single, MultipleAndOrdered)
  170. // ById
  171. EBUS_TEST_ALIAS(ManyToOne, ById, Single)
  172. EBUS_TEST_ALIAS(ManyToMany, ById, Multiple)
  173. EBUS_TEST_ALIAS(ManyToManyOrdered, ById, MultipleAndOrdered)
  174. // ByIdAndOrdered
  175. EBUS_TEST_ALIAS(ManyOrderedToOne, ByIdAndOrdered, Single)
  176. EBUS_TEST_ALIAS(ManyOrderedToMany, ByIdAndOrdered, Multiple)
  177. EBUS_TEST_ALIAS(ManyOrderedToManyOrdered, ByIdAndOrdered, MultipleAndOrdered)
  178. // Handler for multi-address buses
  179. template <typename Bus, AZ::EBusAddressPolicy addressPolicy = Bus::Traits::AddressPolicy>
  180. class Handler
  181. : public BusImplementation::HandlerCommon<Bus>
  182. {
  183. public:
  184. AZ_CLASS_ALLOCATOR(Handler, AZ::SystemAllocator);
  185. Handler(int id, bool connectOnConstruct)
  186. {
  187. m_busId = id;
  188. if (connectOnConstruct)
  189. {
  190. EXPECT_FALSE(this->BusIsConnected());
  191. Connect();
  192. EXPECT_TRUE(this->BusIsConnected());
  193. }
  194. }
  195. Handler(int id, int handlerOrder, bool connectOnConstruct)
  196. : BusImplementation::HandlerCommon<Bus>(handlerOrder)
  197. {
  198. m_busId = id;
  199. if (connectOnConstruct)
  200. {
  201. EXPECT_FALSE(this->BusIsConnected());
  202. Connect();
  203. EXPECT_TRUE(this->BusIsConnected());
  204. }
  205. }
  206. ~Handler() override = default;
  207. // Helper function for connecting without specifying an id
  208. void Connect()
  209. {
  210. this->BusConnect(m_busId);
  211. }
  212. void Disconnect()
  213. {
  214. this->BusDisconnect(m_busId);
  215. }
  216. int OnEvent() override
  217. {
  218. BusImplementation::HandlerCommon<Bus>::OnEvent();
  219. return 1;
  220. }
  221. private:
  222. int m_busId = 0;
  223. };
  224. // Special handler for single address buses
  225. template <typename Bus>
  226. class Handler<Bus, AZ::EBusAddressPolicy::Single>
  227. : public BusImplementation::HandlerCommon<Bus>
  228. {
  229. public:
  230. AZ_CLASS_ALLOCATOR(Handler, AZ::SystemAllocator);
  231. Handler(int, bool connectOnConstruct)
  232. {
  233. if (connectOnConstruct)
  234. {
  235. EXPECT_FALSE(this->BusIsConnected());
  236. Connect();
  237. EXPECT_TRUE(this->BusIsConnected());
  238. }
  239. }
  240. Handler(int, int handlerOrder, bool connectOnConstruct)
  241. : BusImplementation::HandlerCommon<Bus>(handlerOrder)
  242. {
  243. if (connectOnConstruct)
  244. {
  245. EXPECT_FALSE(this->BusIsConnected());
  246. Connect();
  247. EXPECT_TRUE(this->BusIsConnected());
  248. }
  249. }
  250. // Helper function for connecting without specifying an id
  251. void Connect()
  252. {
  253. this->BusConnect();
  254. }
  255. void Disconnect()
  256. {
  257. this->BusDisconnect();
  258. }
  259. int OnEvent() override
  260. {
  261. BusImplementation::HandlerCommon<Bus>::OnEvent();
  262. return 2;
  263. }
  264. };
  265. // Handler for multi-address buses
  266. template <typename Bus>
  267. class MultiHandlerById
  268. : public BusImplementation::MultiHandlerCommon<Bus>
  269. {
  270. public:
  271. AZ_CLASS_ALLOCATOR(MultiHandlerById, AZ::SystemAllocator);
  272. MultiHandlerById(std::initializer_list<int> busIdList)
  273. {
  274. // We will bind at construction time to the bus. Disconnect is automatic when the object is
  275. // destroyed or we can call BusDisconnect()
  276. EXPECT_FALSE(this->BusIsConnected());
  277. Connect(busIdList);
  278. EXPECT_TRUE(this->BusIsConnected());
  279. }
  280. // Helper function for connecting on multiple ids
  281. void Connect(std::initializer_list<int> busIdList)
  282. {
  283. for (int busId : busIdList)
  284. {
  285. this->BusConnect(busId);
  286. }
  287. }
  288. void Disconnect(std::initializer_list<int> busIdList)
  289. {
  290. for (int busId : busIdList)
  291. {
  292. this->BusDisconnect(busId);
  293. }
  294. }
  295. int OnEvent() override
  296. {
  297. return BusImplementation::MultiHandlerCommon<Bus>::OnEvent();
  298. }
  299. };
  300. namespace UnitTest
  301. {
  302. using BusTypesId = ::testing::Types<
  303. ManyToOne, ManyToMany, ManyToManyOrdered,
  304. ManyOrderedToOne, ManyOrderedToMany, ManyOrderedToManyOrdered>;
  305. using BusTypesAll = ::testing::Types<
  306. OneToOne, OneToMany, OneToManyOrdered,
  307. ManyToOne, ManyToMany, ManyToManyOrdered,
  308. ManyOrderedToOne, ManyOrderedToMany, ManyOrderedToManyOrdered>;
  309. template <typename Bus>
  310. class EBusTestAll
  311. : public LeakDetectionFixture
  312. {
  313. public:
  314. using BusHandler = Handler<Bus>;
  315. using BusMultiHandlerById = MultiHandlerById<Bus>;
  316. EBusTestAll()
  317. {
  318. Bus::GetOrCreateContext();
  319. }
  320. void TearDown() override
  321. {
  322. DestroyHandlers();
  323. LeakDetectionFixture::TearDown();
  324. }
  325. //////////////////////////////////////////////////////////////////////////
  326. // Handler Helpers
  327. // Create an appropriate number of handlers for testing
  328. void CreateHandlers()
  329. {
  330. int numAddresses = HasMultipleAddresses() ? 3 : 1;
  331. int numHandlersPerAddress = HasMultipleHandlersPerAddress() ? 3 : 1;
  332. constexpr bool connectOnConstruct{ true };
  333. for (int address = 0; address < numAddresses; ++address)
  334. {
  335. for (int handler = 0; handler < numHandlersPerAddress; ++handler)
  336. {
  337. m_handlers[address].emplace_back(aznew BusHandler(address, connectOnConstruct));
  338. ++m_numHandlers;
  339. }
  340. }
  341. ValidateCalls(0);
  342. }
  343. // Gets the total number of handlers active
  344. int GetNumHandlers()
  345. {
  346. return m_numHandlers;
  347. }
  348. // Clears the handlers list without deleting them (useful for Release tests)
  349. void ClearHandlers()
  350. {
  351. m_handlers.clear();
  352. m_handlers.rehash(0);
  353. m_numHandlers = 0;
  354. }
  355. // Destroy all handlers
  356. void DestroyHandlers()
  357. {
  358. for (const auto& handlerPair : m_handlers)
  359. {
  360. for (BusHandler* handler : handlerPair.second)
  361. {
  362. delete handler;
  363. }
  364. }
  365. ClearHandlers();
  366. EXPECT_FALSE(Bus::HasHandlers());
  367. }
  368. // Ensure that all active handlers have the expected call count, in the correct order
  369. // This should only be called after Broadcast()
  370. void ValidateCalls(int expected, bool isForward = true)
  371. {
  372. for (const auto& handlerPair : m_handlers)
  373. {
  374. ValidateCalls(expected, handlerPair.first, isForward);
  375. }
  376. // Validate address execution order
  377. if (AddressesAreOrdered())
  378. {
  379. // Collect the first handler from each address
  380. using PairType = AZStd::pair<int, BusHandler*>;
  381. AZStd::vector<PairType> sortedHandlers;
  382. for (const auto& handlerPair : m_handlers)
  383. {
  384. PairType pair(handlerPair.first, handlerPair.second.front());
  385. auto insertPos = AZStd::lower_bound(
  386. sortedHandlers.begin(), sortedHandlers.end(),
  387. pair,
  388. [](const PairType& lhs, const PairType& rhs)
  389. {
  390. return lhs.first < rhs.first;
  391. }
  392. );
  393. sortedHandlers.emplace(insertPos, pair);
  394. }
  395. // Iterate over the list, and validate that they were called in the correct order
  396. unsigned int lastExecuted = 0;
  397. for (const PairType& pair : sortedHandlers)
  398. {
  399. if (lastExecuted > 0)
  400. {
  401. if (isForward)
  402. {
  403. EXPECT_LT(lastExecuted, pair.second->m_executedOrder);
  404. }
  405. else
  406. {
  407. EXPECT_GT(lastExecuted, pair.second->m_executedOrder);
  408. }
  409. }
  410. lastExecuted = pair.second->m_executedOrder;
  411. }
  412. }
  413. }
  414. // Ensure that all active handlers have the expected call count, and were called in the correct order
  415. void ValidateCalls(int expected, int id, bool isForward = true)
  416. {
  417. auto& handlers = m_handlers[id];
  418. for (BusHandler* handler : handlers)
  419. {
  420. EXPECT_EQ(expected, handler->m_eventCalls);
  421. }
  422. // Validate handler execution order
  423. if (HandlersAreOrdered())
  424. {
  425. // Sort the handlers the same way we expect the bus to sort them
  426. auto sortedHandlers = handlers;
  427. AZStd::sort(sortedHandlers.begin(), sortedHandlers.end(), AZStd::bind(&BusHandler::Compare, AZStd::placeholders::_1, AZStd::placeholders::_2));
  428. // Iterate over the list, and validate that they were called in the correct order
  429. unsigned int lastExecuted = 0;
  430. for (const BusHandler* handler : sortedHandlers)
  431. {
  432. if (lastExecuted > 0)
  433. {
  434. if (isForward)
  435. {
  436. EXPECT_LT(lastExecuted, handler->m_executedOrder);
  437. }
  438. else
  439. {
  440. EXPECT_GT(lastExecuted, handler->m_executedOrder);
  441. }
  442. }
  443. lastExecuted = handler->m_executedOrder;
  444. }
  445. }
  446. }
  447. //////////////////////////////////////////////////////////////////////////
  448. // Metadata helpers
  449. bool HasMultipleAddresses()
  450. {
  451. return Bus::HasId;
  452. }
  453. bool AddressesAreOrdered()
  454. {
  455. return Bus::Traits::AddressPolicy == EBusAddressPolicy::ByIdAndOrdered;
  456. }
  457. bool HasMultipleHandlersPerAddress()
  458. {
  459. return Bus::Traits::HandlerPolicy != EBusHandlerPolicy::Single;
  460. }
  461. bool HandlersAreOrdered()
  462. {
  463. return Bus::Traits::HandlerPolicy == EBusHandlerPolicy::MultipleAndOrdered;
  464. }
  465. protected:
  466. AZStd::unordered_map<int, AZStd::vector<BusHandler*>> m_handlers;
  467. int m_numHandlers = 0;
  468. };
  469. TYPED_TEST_SUITE(EBusTestAll, BusTypesAll);
  470. template <typename Bus>
  471. class EBusTestId
  472. : public EBusTestAll<Bus>
  473. {
  474. };
  475. TYPED_TEST_SUITE(EBusTestId, BusTypesId);
  476. using BusTypesIdMultiHandlers = ::testing::Types<
  477. ManyToMany, ManyToManyOrdered,
  478. ManyOrderedToMany, ManyOrderedToManyOrdered>;
  479. template <typename Bus>
  480. class EBusTestIdMultiHandlers
  481. : public EBusTestAll<Bus>
  482. {
  483. };
  484. TYPED_TEST_SUITE(EBusTestIdMultiHandlers, BusTypesIdMultiHandlers);
  485. //////////////////////////////////////////////////////////////////////////
  486. // Non-event functions
  487. TYPED_TEST(EBusTestAll, ConnectDisconnect)
  488. {
  489. using Bus = TypeParam;
  490. using Handler = typename EBusTestAll<Bus>::BusHandler;
  491. constexpr bool connectOnConstruct{ true };
  492. Handler meh(0, connectOnConstruct);
  493. EXPECT_EQ(0, meh.m_eventCalls);
  494. EXPECT_TRUE(Bus::HasHandlers());
  495. Bus::Broadcast(&Bus::Events::OnEvent);
  496. EXPECT_EQ(1, meh.m_eventCalls);
  497. EXPECT_TRUE(meh.BusIsConnected());
  498. meh.BusDisconnect(); // we disconnect from receiving events.
  499. EXPECT_FALSE(meh.BusIsConnected());
  500. EXPECT_FALSE(Bus::HasHandlers());
  501. // this signal will NOT trigger any calls.
  502. Bus::Broadcast(&Bus::Events::OnEvent);
  503. EXPECT_EQ(1, meh.m_eventCalls);
  504. }
  505. TYPED_TEST(EBusTestIdMultiHandlers, EnumerateHandlers_MultiHandler)
  506. {
  507. using Bus = TypeParam;
  508. using BusMultiHandlerById = typename EBusTestAll<Bus>::BusMultiHandlerById;
  509. BusMultiHandlerById sourceMultiHandler{ 0, 1, 2 };
  510. BusMultiHandlerById multiHandlerWithOverlappingIds{ 1, 3, 5 };
  511. // Test handlers' enumeration functionality
  512. Bus::EnumerateHandlers([](typename BusMultiHandlerById::Interface* interfaceInst) -> bool
  513. {
  514. interfaceInst->OnEvent();
  515. return true;
  516. });
  517. }
  518. TYPED_TEST(EBusTestId, FindFirstHandler)
  519. {
  520. using Bus = TypeParam;
  521. using Handler = typename EBusTestAll<Bus>::BusHandler;
  522. constexpr bool connectOnConstruct{ true };
  523. Handler meh0(0, connectOnConstruct); /// <-- Bind to bus 0
  524. Handler meh1(1, connectOnConstruct); /// <-- Bind to bus 1
  525. // Test handlers' enumeration functionality
  526. EXPECT_EQ(&meh0, Bus::FindFirstHandler(0));
  527. EXPECT_EQ(&meh1, Bus::FindFirstHandler(1));
  528. EXPECT_EQ(nullptr, Bus::FindFirstHandler(3));
  529. }
  530. //////////////////////////////////////////////////////////////////////////
  531. // Immediate calls
  532. TYPED_TEST(EBusTestAll, Broadcast)
  533. {
  534. using Bus = TypeParam;
  535. this->CreateHandlers();
  536. Bus::Broadcast(&Bus::Events::OnEvent);
  537. this->ValidateCalls(1);
  538. Bus::Broadcast(&Bus::Events::OnEvent);
  539. this->ValidateCalls(2);
  540. }
  541. TYPED_TEST(EBusTestAll, Broadcast_Release)
  542. {
  543. using Bus = TypeParam;
  544. this->CreateHandlers();
  545. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  546. Bus::Broadcast(&Bus::Events::Release);
  547. EXPECT_FALSE(Bus::HasHandlers());
  548. this->ClearHandlers();
  549. }
  550. TYPED_TEST(EBusTestAll, BroadcastReverse)
  551. {
  552. using Bus = TypeParam;
  553. this->CreateHandlers();
  554. Bus::BroadcastReverse(&Bus::Events::OnEvent);
  555. this->ValidateCalls(1, false);
  556. Bus::BroadcastReverse(&Bus::Events::OnEvent);
  557. this->ValidateCalls(2, false);
  558. }
  559. TYPED_TEST(EBusTestAll, BroadcastReverse_Release)
  560. {
  561. using Bus = TypeParam;
  562. this->CreateHandlers();
  563. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  564. Bus::BroadcastReverse(&Bus::Events::Release);
  565. EXPECT_FALSE(Bus::HasHandlers());
  566. this->ClearHandlers();
  567. }
  568. TYPED_TEST(EBusTestAll, BroadcastResult)
  569. {
  570. using Bus = TypeParam;
  571. this->CreateHandlers();
  572. int result = -1;
  573. Bus::BroadcastResult(result, &Bus::Events::OnEvent);
  574. EXPECT_LT(0, result);
  575. this->ValidateCalls(1);
  576. result = -1;
  577. Bus::BroadcastResult(result, &Bus::Events::OnEvent);
  578. EXPECT_LT(0, result);
  579. this->ValidateCalls(2);
  580. this->DestroyHandlers();
  581. result = -1;
  582. Bus::BroadcastResult(result, &Bus::Events::OnEvent);
  583. EXPECT_EQ(-1, result);
  584. }
  585. TYPED_TEST(EBusTestAll, BroadcastResultReverse)
  586. {
  587. using Bus = TypeParam;
  588. this->CreateHandlers();
  589. int result = -1;
  590. Bus::BroadcastResultReverse(result, &Bus::Events::OnEvent);
  591. EXPECT_LT(0, result);
  592. this->ValidateCalls(1, false);
  593. result = -1;
  594. Bus::BroadcastResultReverse(result, &Bus::Events::OnEvent);
  595. EXPECT_LT(0, result);
  596. this->ValidateCalls(2, false);
  597. this->DestroyHandlers();
  598. result = -1;
  599. Bus::BroadcastResultReverse(result, &Bus::Events::OnEvent);
  600. EXPECT_EQ(-1, result);
  601. }
  602. // Test sending events on an address
  603. TYPED_TEST(EBusTestId, Event)
  604. {
  605. using Bus = TypeParam;
  606. this->CreateHandlers();
  607. // Signal OnEvent event on bus 1
  608. Bus::Event(1, &Bus::Events::OnEvent);
  609. // Validate bus 1 has 2 calls, all others have 1
  610. this->ValidateCalls(1, 1);
  611. this->ValidateCalls(0, 2);
  612. this->ValidateCalls(0, 3);
  613. }
  614. // Test sending events on an address
  615. TYPED_TEST(EBusTestId, Event_Release)
  616. {
  617. using Bus = TypeParam;
  618. this->CreateHandlers();
  619. for (const auto& handlerPair : this->m_handlers)
  620. {
  621. Bus::Event(handlerPair.first, &Bus::Events::Release);
  622. }
  623. EXPECT_FALSE(Bus::HasHandlers());
  624. this->ClearHandlers();
  625. }
  626. // Test sending events on an address
  627. TYPED_TEST(EBusTestId, EventReverse)
  628. {
  629. using Bus = TypeParam;
  630. this->CreateHandlers();
  631. // Signal OnEvent event on bus 1
  632. Bus::EventReverse(1, &Bus::Events::OnEvent);
  633. // Validate bus 1 has 2 calls, all others have 1
  634. this->ValidateCalls(1, 1, false);
  635. this->ValidateCalls(0, 2, false);
  636. this->ValidateCalls(0, 3, false);
  637. }
  638. // Test sending events (that delete this) on an address, backwards
  639. TYPED_TEST(EBusTestId, EventReverse_Release)
  640. {
  641. using Bus = TypeParam;
  642. this->CreateHandlers();
  643. for (const auto& handlerPair : this->m_handlers)
  644. {
  645. Bus::EventReverse(handlerPair.first, &Bus::Events::Release);
  646. }
  647. EXPECT_FALSE(Bus::HasHandlers());
  648. this->ClearHandlers();
  649. }
  650. // Test sending events with results on an address
  651. TYPED_TEST(EBusTestId, EventResult)
  652. {
  653. using Bus = TypeParam;
  654. this->CreateHandlers();
  655. // Signal OnEvent event on bus 1
  656. int result = -1;
  657. Bus::EventResult(result, 1, &Bus::Events::OnEvent);
  658. EXPECT_LT(0, result);
  659. // Validate bus 1 has 2 calls, all others have 1
  660. this->ValidateCalls(1, 1);
  661. this->ValidateCalls(0, 2);
  662. this->ValidateCalls(0, 3);
  663. this->DestroyHandlers();
  664. result = -1;
  665. Bus::EventResult(result, 1, &Bus::Events::OnEvent);
  666. EXPECT_EQ(-1, result);
  667. }
  668. // Test sending events with results on an address
  669. TYPED_TEST(EBusTestId, EventResultReverse)
  670. {
  671. using Bus = TypeParam;
  672. this->CreateHandlers();
  673. // Signal OnEvent event on bus 1
  674. int result = -1;
  675. Bus::EventResultReverse(result, 1, &Bus::Events::OnEvent);
  676. EXPECT_LT(0, result);
  677. // Validate bus 1 has 2 calls, all others have 1
  678. this->ValidateCalls(1, 1, false);
  679. this->ValidateCalls(0, 2, false);
  680. this->ValidateCalls(0, 3, false);
  681. this->DestroyHandlers();
  682. result = -1;
  683. Bus::EventResultReverse(result, 1, &Bus::Events::OnEvent);
  684. EXPECT_EQ(-1, result);
  685. }
  686. // Test sending events on a bound bus ptr
  687. TYPED_TEST(EBusTestId, BindEvent)
  688. {
  689. using Bus = TypeParam;
  690. this->CreateHandlers();
  691. typename Bus::BusPtr ptr;
  692. Bus::Bind(ptr, 1);
  693. EXPECT_NE(nullptr, ptr);
  694. // Signal OnEvent event on bus 1
  695. Bus::Event(ptr, &Bus::Events::OnEvent);
  696. // Validate bus 1 has 2 calls, all others have 1
  697. this->ValidateCalls(1, 1);
  698. this->ValidateCalls(0, 2);
  699. this->ValidateCalls(0, 3);
  700. this->DestroyHandlers();
  701. // Validate that broadcasting/eventing after binding disconnecting all doesn't crash
  702. Bus::Broadcast(&Bus::Events::OnEvent);
  703. Bus::Event(ptr, &Bus::Events::OnEvent);
  704. Bus::Event(1, &Bus::Events::OnEvent);
  705. }
  706. // Test sending events (that delete this) on a bound bus ptr
  707. TYPED_TEST(EBusTestId, BindEvent_Release)
  708. {
  709. using Bus = TypeParam;
  710. this->CreateHandlers();
  711. typename Bus::BusPtr ptr;
  712. for (const auto& handlerPair : this->m_handlers)
  713. {
  714. Bus::Bind(ptr, handlerPair.first);
  715. EXPECT_NE(nullptr, ptr);
  716. Bus::Event(ptr, &Bus::Events::Release);
  717. }
  718. EXPECT_FALSE(Bus::HasHandlers());
  719. this->ClearHandlers();
  720. }
  721. // Test sending events on a bound bus ptr, backwards
  722. TYPED_TEST(EBusTestId, BindEventReverse)
  723. {
  724. using Bus = TypeParam;
  725. this->CreateHandlers();
  726. typename Bus::BusPtr ptr;
  727. Bus::Bind(ptr, 1);
  728. EXPECT_NE(nullptr, ptr);
  729. // Signal OnEvent event on bus 1
  730. Bus::EventReverse(ptr, &Bus::Events::OnEvent);
  731. // Validate bus 1 has 2 calls, all others have 1
  732. this->ValidateCalls(1, 1, false);
  733. this->ValidateCalls(0, 2, false);
  734. this->ValidateCalls(0, 3, false);
  735. this->DestroyHandlers();
  736. // Validate that broadcasting/eventing after binding disconnecting all doesn't crash
  737. Bus::BroadcastReverse(&Bus::Events::OnEvent);
  738. Bus::EventReverse(ptr, &Bus::Events::OnEvent);
  739. Bus::EventReverse(1, &Bus::Events::OnEvent);
  740. }
  741. // Test sending events (that delete this) on a bound bus ptr, backwards
  742. TYPED_TEST(EBusTestId, BindEventReverse_Release)
  743. {
  744. using Bus = TypeParam;
  745. this->CreateHandlers();
  746. typename Bus::BusPtr ptr;
  747. for (const auto& handlerPair : this->m_handlers)
  748. {
  749. Bus::Bind(ptr, handlerPair.first);
  750. EXPECT_NE(nullptr, ptr);
  751. Bus::EventReverse(ptr, &Bus::Events::Release);
  752. }
  753. EXPECT_FALSE(Bus::HasHandlers());
  754. this->ClearHandlers();
  755. }
  756. // Test sending events on a bound bus ptr
  757. TYPED_TEST(EBusTestId, BindEventResult)
  758. {
  759. using Bus = TypeParam;
  760. this->CreateHandlers();
  761. typename Bus::BusPtr ptr;
  762. Bus::Bind(ptr, 1);
  763. EXPECT_NE(nullptr, ptr);
  764. // Signal OnEvent event on bus 1
  765. int result = -1;
  766. Bus::EventResult(result, ptr, &Bus::Events::OnEvent);
  767. EXPECT_LT(0, result);
  768. // Validate bus 1 has 2 calls, all others have 1
  769. this->ValidateCalls(1, 1);
  770. this->ValidateCalls(0, 2);
  771. this->ValidateCalls(0, 3);
  772. this->DestroyHandlers();
  773. // Validate that broadcasting/eventing after binding disconnecting all doesn't crash
  774. Bus::Broadcast(&Bus::Events::OnEvent);
  775. Bus::Event(ptr, &Bus::Events::OnEvent);
  776. Bus::Event(1, &Bus::Events::OnEvent);
  777. }
  778. // Test sending events on a bound bus ptr, backwards
  779. TYPED_TEST(EBusTestId, BindEventResultReverse)
  780. {
  781. using Bus = TypeParam;
  782. this->CreateHandlers();
  783. typename Bus::BusPtr ptr;
  784. Bus::Bind(ptr, 1);
  785. EXPECT_NE(nullptr, ptr);
  786. // Signal OnEvent event on bus 1
  787. int result = -1;
  788. Bus::EventResultReverse(result, ptr, &Bus::Events::OnEvent);
  789. EXPECT_LT(0, result);
  790. // Validate bus 1 has 2 calls, all others have 1
  791. this->ValidateCalls(1, 1, false);
  792. this->ValidateCalls(0, 2, false);
  793. this->ValidateCalls(0, 3, false);
  794. this->DestroyHandlers();
  795. // Validate that broadcasting/eventing after binding disconnecting all doesn't crash
  796. Bus::BroadcastReverse(&Bus::Events::OnEvent);
  797. Bus::EventReverse(ptr, &Bus::Events::OnEvent);
  798. Bus::EventReverse(1, &Bus::Events::OnEvent);
  799. }
  800. //////////////////////////////////////////////////////////////////////////
  801. // Queued calls
  802. TYPED_TEST(EBusTestAll, QueueBroadcast)
  803. {
  804. using Bus = TypeParam;
  805. this->CreateHandlers();
  806. Bus::QueueBroadcast(&Bus::Events::OnEvent);
  807. this->ValidateCalls(0);
  808. Bus::ExecuteQueuedEvents();
  809. this->ValidateCalls(1);
  810. Bus::QueueBroadcast(&Bus::Events::OnEvent);
  811. this->ValidateCalls(1);
  812. Bus::ExecuteQueuedEvents();
  813. this->ValidateCalls(2);
  814. }
  815. TYPED_TEST(EBusTestAll, QueueBroadcast_Release)
  816. {
  817. using Bus = TypeParam;
  818. this->CreateHandlers();
  819. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  820. Bus::QueueBroadcast(&Bus::Events::Release);
  821. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  822. Bus::ExecuteQueuedEvents();
  823. EXPECT_FALSE(Bus::HasHandlers());
  824. this->ClearHandlers();
  825. }
  826. TYPED_TEST(EBusTestAll, QueueBroadcastReverse)
  827. {
  828. using Bus = TypeParam;
  829. this->CreateHandlers();
  830. Bus::QueueBroadcastReverse(&Bus::Events::OnEvent);
  831. this->ValidateCalls(0, false);
  832. Bus::ExecuteQueuedEvents();
  833. this->ValidateCalls(1, false);
  834. Bus::QueueBroadcastReverse(&Bus::Events::OnEvent);
  835. this->ValidateCalls(1, false);
  836. Bus::ExecuteQueuedEvents();
  837. this->ValidateCalls(2, false);
  838. }
  839. TYPED_TEST(EBusTestAll, QueueBroadcastReverse_Release)
  840. {
  841. using Bus = TypeParam;
  842. this->CreateHandlers();
  843. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  844. Bus::QueueBroadcastReverse(&Bus::Events::Release);
  845. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  846. Bus::ExecuteQueuedEvents();
  847. EXPECT_FALSE(Bus::HasHandlers());
  848. this->ClearHandlers();
  849. }
  850. // Test sending events on an address
  851. TYPED_TEST(EBusTestId, QueueEvent)
  852. {
  853. using Bus = TypeParam;
  854. this->CreateHandlers();
  855. // Signal OnEvent event on bus 1
  856. Bus::QueueEvent(1, &Bus::Events::OnEvent);
  857. this->ValidateCalls(0);
  858. Bus::ExecuteQueuedEvents();
  859. // Validate bus 1 has 1 calls, all others have 0
  860. this->ValidateCalls(1, 1);
  861. this->ValidateCalls(0, 2);
  862. this->ValidateCalls(0, 3);
  863. }
  864. // Test sending events on an address
  865. TYPED_TEST(EBusTestId, QueueEvent_Release)
  866. {
  867. using Bus = TypeParam;
  868. this->CreateHandlers();
  869. for (const auto& handlerPair : this->m_handlers)
  870. {
  871. Bus::QueueEvent(handlerPair.first, &Bus::Events::Release);
  872. }
  873. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  874. Bus::ExecuteQueuedEvents();
  875. EXPECT_FALSE(Bus::HasHandlers());
  876. this->ClearHandlers();
  877. }
  878. // Test sending events on an address
  879. TYPED_TEST(EBusTestId, QueueEventReverse)
  880. {
  881. using Bus = TypeParam;
  882. this->CreateHandlers();
  883. // Signal OnEvent event on bus 1
  884. Bus::QueueEventReverse(1, &Bus::Events::OnEvent);
  885. this->ValidateCalls(0);
  886. Bus::ExecuteQueuedEvents();
  887. // Validate bus 1 has 2 calls, all others have 1
  888. this->ValidateCalls(1, 1, false);
  889. this->ValidateCalls(0, 2, false);
  890. this->ValidateCalls(0, 3, false);
  891. }
  892. // Test sending events (that delete this) on an address, backwards
  893. TYPED_TEST(EBusTestId, QueueEventReverse_Release)
  894. {
  895. using Bus = TypeParam;
  896. this->CreateHandlers();
  897. for (const auto& handlerPair : this->m_handlers)
  898. {
  899. Bus::QueueEventReverse(handlerPair.first, &Bus::Events::Release);
  900. }
  901. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  902. Bus::ExecuteQueuedEvents();
  903. EXPECT_FALSE(Bus::HasHandlers());
  904. this->ClearHandlers();
  905. }
  906. // Test sending events on a bound bus ptr
  907. TYPED_TEST(EBusTestId, QueueBindEvent)
  908. {
  909. using Bus = TypeParam;
  910. this->CreateHandlers();
  911. typename Bus::BusPtr ptr;
  912. Bus::Bind(ptr, 1);
  913. EXPECT_NE(nullptr, ptr);
  914. // Signal OnEvent event on bus 1
  915. Bus::QueueEvent(ptr, &Bus::Events::OnEvent);
  916. this->ValidateCalls(0);
  917. Bus::ExecuteQueuedEvents();
  918. // Validate bus 1 has 2 calls, all others have 1
  919. this->ValidateCalls(1, 1);
  920. this->ValidateCalls(0, 2);
  921. this->ValidateCalls(0, 3);
  922. }
  923. // Test sending events (that delete this) on a bound bus ptr
  924. TYPED_TEST(EBusTestId, QueueBindEvent_Release)
  925. {
  926. using Bus = TypeParam;
  927. this->CreateHandlers();
  928. typename Bus::BusPtr ptr;
  929. for (const auto& handlerPair : this->m_handlers)
  930. {
  931. Bus::Bind(ptr, handlerPair.first);
  932. EXPECT_NE(nullptr, ptr);
  933. Bus::QueueEvent(ptr, &Bus::Events::Release);
  934. }
  935. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  936. Bus::ExecuteQueuedEvents();
  937. EXPECT_FALSE(Bus::HasHandlers());
  938. this->ClearHandlers();
  939. }
  940. // Test sending events on a bound bus ptr, backwards
  941. TYPED_TEST(EBusTestId, QueueBindEventReverse)
  942. {
  943. using Bus = TypeParam;
  944. this->CreateHandlers();
  945. typename Bus::BusPtr ptr;
  946. Bus::Bind(ptr, 1);
  947. EXPECT_NE(nullptr, ptr);
  948. // Signal OnEvent event on bus 1
  949. Bus::QueueEventReverse(ptr, &Bus::Events::OnEvent);
  950. this->ValidateCalls(0);
  951. Bus::ExecuteQueuedEvents();
  952. // Validate bus 1 has 2 calls, all others have 1
  953. this->ValidateCalls(1, 1, false);
  954. this->ValidateCalls(0, 2, false);
  955. this->ValidateCalls(0, 3, false);
  956. }
  957. // Test sending events (that delete this) on a bound bus ptr, backwards
  958. TYPED_TEST(EBusTestId, QueueBindEventReverse_Release)
  959. {
  960. using Bus = TypeParam;
  961. this->CreateHandlers();
  962. typename Bus::BusPtr ptr;
  963. for (const auto& handlerPair : this->m_handlers)
  964. {
  965. Bus::Bind(ptr, handlerPair.first);
  966. EXPECT_NE(nullptr, ptr);
  967. Bus::QueueEventReverse(ptr, &Bus::Events::Release);
  968. }
  969. EXPECT_EQ(this->GetNumHandlers(), Bus::GetTotalNumOfEventHandlers());
  970. Bus::ExecuteQueuedEvents();
  971. EXPECT_FALSE(Bus::HasHandlers());
  972. this->ClearHandlers();
  973. }
  974. //////////////////////////////////////////////////////////////////////////
  975. // GetCurrentBusId calls
  976. TYPED_TEST(EBusTestId, Event_GetCurrentBusId_ReturnsNonNullptr)
  977. {
  978. using Bus = TypeParam;
  979. this->CreateHandlers();
  980. auto busCallback = [](typename Bus::InterfaceType*)
  981. {
  982. const int* busId = Bus::GetCurrentBusId();
  983. ASSERT_NE(nullptr, busId);
  984. EXPECT_EQ(1, *busId);
  985. };
  986. Bus::Event(1, busCallback);
  987. this->DestroyHandlers();
  988. }
  989. TYPED_TEST(EBusTestId, EventResult_GetCurrentBusId_ReturnsNonNullptr)
  990. {
  991. using Bus = TypeParam;
  992. this->CreateHandlers();
  993. auto busCallback = [](typename Bus::InterfaceType*) -> const char*
  994. {
  995. const int* busId = Bus::GetCurrentBusId();
  996. EXPECT_NE(nullptr, busId);
  997. if (busId)
  998. {
  999. EXPECT_EQ(1, *busId);
  1000. }
  1001. return "BusType";
  1002. };
  1003. const char* result{};
  1004. Bus::EventResult(result, 1, busCallback);
  1005. EXPECT_STREQ("BusType", result);
  1006. this->DestroyHandlers();
  1007. }
  1008. TYPED_TEST(EBusTestId, EventReverse_GetCurrentBusId_ReturnsNonNullptr)
  1009. {
  1010. using Bus = TypeParam;
  1011. this->CreateHandlers();
  1012. auto busCallback = [](typename Bus::InterfaceType*)
  1013. {
  1014. const int* busId = Bus::GetCurrentBusId();
  1015. ASSERT_NE(nullptr, busId);
  1016. EXPECT_EQ(1, *busId);
  1017. };
  1018. Bus::EventReverse(1, busCallback);
  1019. this->DestroyHandlers();
  1020. }
  1021. TYPED_TEST(EBusTestId, EventResultReverse_GetCurrentBusId_ReturnsNonNullptr)
  1022. {
  1023. using Bus = TypeParam;
  1024. this->CreateHandlers();
  1025. auto busCallback = [](typename Bus::InterfaceType*)
  1026. {
  1027. const int* busId = Bus::GetCurrentBusId();
  1028. EXPECT_NE(nullptr, busId);
  1029. if (busId)
  1030. {
  1031. EXPECT_EQ(1, *busId);
  1032. }
  1033. return 7;
  1034. };
  1035. int32_t result{};
  1036. Bus::EventResultReverse(result, 1, busCallback);
  1037. EXPECT_EQ(7, result);
  1038. this->DestroyHandlers();
  1039. }
  1040. TYPED_TEST(EBusTestId, BindEvent_GetCurrentBusId_ReturnsNonNullptr)
  1041. {
  1042. using Bus = TypeParam;
  1043. this->CreateHandlers();
  1044. typename Bus::BusPtr ptr;
  1045. auto busCallback = [](typename Bus::InterfaceType*)
  1046. {
  1047. EXPECT_NE(nullptr, Bus::GetCurrentBusId());
  1048. };
  1049. for (const auto& handlerPair : this->m_handlers)
  1050. {
  1051. Bus::Bind(ptr, handlerPair.first);
  1052. EXPECT_NE(nullptr, ptr);
  1053. Bus::Event(ptr, busCallback);
  1054. }
  1055. this->DestroyHandlers();
  1056. }
  1057. TYPED_TEST(EBusTestId, BindEventResult_GetCurrentBusId_ReturnsNonNullptr)
  1058. {
  1059. using Bus = TypeParam;
  1060. this->CreateHandlers();
  1061. typename Bus::BusPtr ptr;
  1062. auto busCallback = [](typename Bus::InterfaceType*)
  1063. {
  1064. EXPECT_NE(nullptr, Bus::GetCurrentBusId());
  1065. return true;
  1066. };
  1067. for (const auto& handlerPair : this->m_handlers)
  1068. {
  1069. Bus::Bind(ptr, handlerPair.first);
  1070. EXPECT_NE(nullptr, ptr);
  1071. bool result{};
  1072. Bus::EventResult(result, ptr, busCallback);
  1073. EXPECT_TRUE(result);
  1074. }
  1075. this->DestroyHandlers();
  1076. }
  1077. TYPED_TEST(EBusTestId, BindEventReverse_GetCurrentBusId_ReturnsNonNullptr)
  1078. {
  1079. using Bus = TypeParam;
  1080. this->CreateHandlers();
  1081. typename Bus::BusPtr ptr;
  1082. auto busCallback = [](typename Bus::InterfaceType*)
  1083. {
  1084. EXPECT_NE(nullptr, Bus::GetCurrentBusId());
  1085. };
  1086. for (const auto& handlerPair : this->m_handlers)
  1087. {
  1088. Bus::Bind(ptr, handlerPair.first);
  1089. EXPECT_NE(nullptr, ptr);
  1090. Bus::EventReverse(ptr, busCallback);
  1091. }
  1092. this->DestroyHandlers();
  1093. }
  1094. TYPED_TEST(EBusTestId, BindEventResultReverse_GetCurrentBusId_ReturnsNonNullptr)
  1095. {
  1096. using Bus = TypeParam;
  1097. this->CreateHandlers();
  1098. typename Bus::BusPtr ptr;
  1099. auto busCallback = [](typename Bus::InterfaceType*)
  1100. {
  1101. EXPECT_NE(nullptr, Bus::GetCurrentBusId());
  1102. return true;
  1103. };
  1104. for (const auto& handlerPair : this->m_handlers)
  1105. {
  1106. Bus::Bind(ptr, handlerPair.first);
  1107. EXPECT_NE(nullptr, ptr);
  1108. bool result{};
  1109. Bus::EventResultReverse(result, ptr, busCallback);
  1110. EXPECT_TRUE(result);
  1111. }
  1112. this->DestroyHandlers();
  1113. }
  1114. TYPED_TEST(EBusTestId, Broadcast_GetCurrentBusId_ReturnsNonNullptr)
  1115. {
  1116. using Bus = TypeParam;
  1117. this->CreateHandlers();
  1118. auto busCallback = [](typename Bus::InterfaceType*)
  1119. {
  1120. const int* busId = Bus::GetCurrentBusId();
  1121. EXPECT_NE(nullptr, busId);
  1122. };
  1123. Bus::Broadcast(busCallback);
  1124. this->DestroyHandlers();
  1125. }
  1126. TYPED_TEST(EBusTestId, BroadcastResult_GetCurrentBusId_ReturnsNonNullptr)
  1127. {
  1128. using Bus = TypeParam;
  1129. this->CreateHandlers();
  1130. auto busCallback = [](typename Bus::InterfaceType*)
  1131. {
  1132. const int* busId = Bus::GetCurrentBusId();
  1133. EXPECT_NE(nullptr, busId);
  1134. return 16.0f;
  1135. };
  1136. float result{};
  1137. Bus::BroadcastResult(result, busCallback);
  1138. EXPECT_FLOAT_EQ(16.0f, result);
  1139. this->DestroyHandlers();
  1140. }
  1141. TYPED_TEST(EBusTestId, BroadcastReverse_GetCurrentBusId_ReturnsNonNullptr)
  1142. {
  1143. using Bus = TypeParam;
  1144. this->CreateHandlers();
  1145. auto busCallback = [](typename Bus::InterfaceType*)
  1146. {
  1147. const int* busId = Bus::GetCurrentBusId();
  1148. EXPECT_NE(nullptr, busId);
  1149. };
  1150. Bus::BroadcastReverse(busCallback);
  1151. this->DestroyHandlers();
  1152. }
  1153. TYPED_TEST(EBusTestId, BroadcastResultReverse_GetCurrentBusId_ReturnsNonNullptr)
  1154. {
  1155. using Bus = TypeParam;
  1156. this->CreateHandlers();
  1157. auto busCallback = [](typename Bus::InterfaceType*)
  1158. {
  1159. const int* busId = Bus::GetCurrentBusId();
  1160. EXPECT_NE(nullptr, busId);
  1161. return 8.0;
  1162. };
  1163. double result{};
  1164. Bus::BroadcastResultReverse(result, busCallback);
  1165. EXPECT_DOUBLE_EQ(8.0, result);
  1166. this->DestroyHandlers();
  1167. }
  1168. TYPED_TEST(EBusTestId, EnumerateHandlers_GetCurrentBusId_ReturnsNonNullptr)
  1169. {
  1170. using Bus = TypeParam;
  1171. this->CreateHandlers();
  1172. auto busCallback = [](typename Bus::InterfaceType*)
  1173. {
  1174. const int* busId = Bus::GetCurrentBusId();
  1175. EXPECT_NE(nullptr, busId);
  1176. return true;
  1177. };
  1178. Bus::EnumerateHandlers(busCallback);
  1179. this->DestroyHandlers();
  1180. }
  1181. TYPED_TEST(EBusTestId, EnumerateHandlersId_GetCurrentBusId_ReturnsNonNullptr)
  1182. {
  1183. using Bus = TypeParam;
  1184. this->CreateHandlers();
  1185. auto busCallback = [](typename Bus::InterfaceType*)
  1186. {
  1187. const int* busId = Bus::GetCurrentBusId();
  1188. EXPECT_NE(nullptr, busId);
  1189. if (busId)
  1190. {
  1191. EXPECT_EQ(1, *busId);
  1192. }
  1193. return true;
  1194. };
  1195. Bus::EnumerateHandlersId(1, busCallback);
  1196. this->DestroyHandlers();
  1197. }
  1198. TYPED_TEST(EBusTestId, EnumerateHandlersPtr_GetCurrentBusId_ReturnsNonNullptr)
  1199. {
  1200. using Bus = TypeParam;
  1201. this->CreateHandlers();
  1202. auto busCallback = [](typename Bus::InterfaceType*)
  1203. {
  1204. const int* busId = Bus::GetCurrentBusId();
  1205. EXPECT_NE(nullptr, busId);
  1206. if(busId)
  1207. {
  1208. EXPECT_EQ(1, *busId);
  1209. }
  1210. return true;
  1211. };
  1212. typename Bus::BusPtr busPtr;
  1213. Bus::Bind(busPtr, 1);
  1214. EXPECT_NE(nullptr, busPtr);
  1215. Bus::EnumerateHandlersPtr(busPtr, busCallback);
  1216. this->DestroyHandlers();
  1217. }
  1218. class EBus
  1219. : public LeakDetectionFixture
  1220. {};
  1221. TEST_F(EBus, DISABLED_CopyConstructorOfEBusHandlerDoesNotAssertInInternalDestructorOfHandler)
  1222. {
  1223. AZ_TEST_START_TRACE_SUPPRESSION;
  1224. {
  1225. MutexBusHandler sourceHandler;
  1226. // Connect source handler to InterfaceWithMutexBus and then copy it over to a new instance
  1227. // Afterwards disconnect the source handler from the InterfaceWithMutexBus
  1228. sourceHandler.BusConnect(1);
  1229. MutexBusHandler targetHandler(sourceHandler);
  1230. sourceHandler.BusDisconnect();
  1231. }
  1232. AZ_TEST_STOP_TRACE_SUPPRESSION(0);
  1233. }
  1234. TEST_F(EBus, DISABLED_CopyAssignmentOfEBusHandlerDoesNotAssertInInternalDestructorOfHandler)
  1235. {
  1236. AZ_TEST_START_TRACE_SUPPRESSION;
  1237. {
  1238. MutexBusHandler sourceHandler;
  1239. MutexBusHandler targetHandler;
  1240. // Connect source handler to InterfaceWithMutexBus and then copy it over to a new instance
  1241. // Afterwards disconnect the source handler from the InterfaceWithMutexBus
  1242. sourceHandler.BusConnect(1);
  1243. targetHandler = sourceHandler;
  1244. sourceHandler.BusDisconnect();
  1245. }
  1246. AZ_TEST_STOP_TRACE_SUPPRESSION(0);
  1247. }
  1248. TEST_F(EBus, CopyConstructorOfEBusHandler_CopyFromConnected_DoesNotAssert)
  1249. {
  1250. AZ_TEST_START_TRACE_SUPPRESSION;
  1251. {
  1252. MutexBusHandler sourceHandler;
  1253. // Connect source handler to InterfaceWithMutexBus and then copy it over to a new instance
  1254. // Afterwards disconnect the source handler from the InterfaceWithMutexBus
  1255. sourceHandler.BusConnect(1);
  1256. // Copy behavior which connects to source handler's bus if
  1257. // Source handler was connected may be unexpected but it should not assert
  1258. MutexBusHandler targetHandler(sourceHandler);
  1259. sourceHandler.BusDisconnect();
  1260. targetHandler.BusDisconnect();
  1261. }
  1262. AZ_TEST_STOP_TRACE_SUPPRESSION(0);
  1263. }
  1264. TEST_F(EBus, CopyOperatorOfEBusHandler_CopyToConnected_DoesNotAssert)
  1265. {
  1266. AZ_TEST_START_TRACE_SUPPRESSION;
  1267. {
  1268. MutexBusHandler targetHandler;
  1269. // Connect source handler to InterfaceWithMutexBus and then copy it over to a new instance
  1270. // Afterwards disconnect the source handler from the InterfaceWithMutexBus
  1271. targetHandler.BusConnect(1);
  1272. // Copy behavior which connects to source handler's bus if
  1273. // Source handler was connected may be unexpected but it should not assert
  1274. MutexBusHandler sourceHandler;
  1275. targetHandler = sourceHandler;
  1276. sourceHandler.BusDisconnect();
  1277. targetHandler.BusDisconnect();
  1278. }
  1279. AZ_TEST_STOP_TRACE_SUPPRESSION(0);
  1280. }
  1281. /**
  1282. * Tests multi-bus handler (a singe ebus instance that can connect to multiple buses)
  1283. */
  1284. namespace MultBusHandler
  1285. {
  1286. /**
  1287. * Create event that allows MULTI buses. By default we already allow multiple handlers per bus.
  1288. */
  1289. class MyEventGroup
  1290. : public AZ::EBusTraits
  1291. {
  1292. public:
  1293. //////////////////////////////////////////////////////////////////////////
  1294. // EBus interface settings
  1295. static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple;
  1296. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  1297. typedef int BusIdType;
  1298. //////////////////////////////////////////////////////////////////////////
  1299. virtual ~MyEventGroup() {}
  1300. //////////////////////////////////////////////////////////////////////////
  1301. // Define the events in this event group!
  1302. virtual void OnAction(float x, float y) = 0;
  1303. virtual float OnSum(float x, float y) = 0;
  1304. //////////////////////////////////////////////////////////////////////////
  1305. };
  1306. typedef AZ::EBus< MyEventGroup > MyEventGroupBus;
  1307. /**
  1308. * Now implement our event handler.
  1309. */
  1310. class MyEventHandler
  1311. : public MyEventGroupBus::MultiHandler
  1312. {
  1313. public:
  1314. int actionCalls;
  1315. int sumCalls;
  1316. MyEventHandler(MyEventGroupBus::BusIdType busId0, MyEventGroupBus::BusIdType busId1)
  1317. : actionCalls(0)
  1318. , sumCalls(0)
  1319. {
  1320. BusConnect(busId0); // connect to the specific bus
  1321. BusConnect(busId1); // connect to the specific bus
  1322. }
  1323. //////////////////////////////////////////////////////////////////////////
  1324. // Implement some action on the events...
  1325. void OnAction(float x, float y) override
  1326. {
  1327. AZ_Printf("UnitTest", "OnAction1(%.2f,%.2f) called\n", x, y); ++actionCalls;
  1328. }
  1329. float OnSum(float x, float y) override
  1330. {
  1331. float sum = x + y; AZ_Printf("UnitTest", "%.2f OnAction1(%.2f,%.2f) on called\n", sum, x, y); ++sumCalls; return sum;
  1332. }
  1333. //////////////////////////////////////////////////////////////////////////
  1334. };
  1335. }
  1336. TEST_F(EBus, MultBusHandler)
  1337. {
  1338. using namespace MultBusHandler;
  1339. {
  1340. MyEventHandler meh0(0, 1); /// <-- Bind to bus 0 and 1
  1341. // Signal OnAction event on all buses
  1342. MyEventGroupBus::Broadcast(&MyEventGroupBus::Events::OnAction, 1.0f, 2.0f);
  1343. EXPECT_EQ(2, meh0.actionCalls);
  1344. // Signal OnSum event
  1345. MyEventGroupBus::Broadcast(&MyEventGroupBus::Events::OnSum, 2.0f, 5.0f);
  1346. EXPECT_EQ(2, meh0.sumCalls);
  1347. // Signal OnAction event on bus 0
  1348. MyEventGroupBus::Event(0, &MyEventGroupBus::Events::OnAction, 1.0f, 2.0f);
  1349. EXPECT_EQ(3, meh0.actionCalls);
  1350. // Signal OnAction event on bus 1
  1351. MyEventGroupBus::Event(1, &MyEventGroupBus::Events::OnAction, 1.0f, 2.0f);
  1352. EXPECT_EQ(4, meh0.actionCalls);
  1353. meh0.BusDisconnect(1); // we disconnect from receiving events on bus 1
  1354. MyEventGroupBus::Broadcast(&MyEventGroupBus::Events::OnAction, 1.0f, 2.0f); // this signal will NOT trigger only one call
  1355. EXPECT_EQ(5, meh0.actionCalls);
  1356. }
  1357. }
  1358. /**
  1359. *
  1360. */
  1361. namespace QueueMessageTest
  1362. {
  1363. class QueueTestEventsMultiBus
  1364. : public EBusTraits
  1365. {
  1366. public:
  1367. //////////////////////////////////////////////////////////////////////////
  1368. // EBusTraits overrides
  1369. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  1370. typedef AZStd::mutex MutexType;
  1371. typedef int BusIdType;
  1372. static const bool EnableEventQueue = true;
  1373. //////////////////////////////////////////////////////////////////////////
  1374. QueueTestEventsMultiBus()
  1375. : m_callCount(0) {}
  1376. virtual ~QueueTestEventsMultiBus() {}
  1377. virtual void OnMessage() { m_callCount++; }
  1378. int m_callCount;
  1379. };
  1380. typedef AZ::EBus<QueueTestEventsMultiBus> QueueTestMultiBus;
  1381. class QueueTestEventsSingleBus
  1382. : public EBusTraits
  1383. {
  1384. public:
  1385. //////////////////////////////////////////////////////////////////////////
  1386. // EBusTraits overrides
  1387. typedef AZStd::mutex MutexType;
  1388. static const bool EnableEventQueue = true;
  1389. //////////////////////////////////////////////////////////////////////////
  1390. QueueTestEventsSingleBus()
  1391. : m_callCount(0) {}
  1392. virtual ~QueueTestEventsSingleBus() {}
  1393. virtual void OnMessage() { m_callCount++; }
  1394. int m_callCount;
  1395. };
  1396. typedef AZ::EBus<QueueTestEventsSingleBus> QueueTestSingleBus;
  1397. JobManager* m_jobManager = nullptr;
  1398. JobContext* m_jobContext = nullptr;
  1399. QueueTestMultiBus::Handler* m_multiHandler = nullptr;
  1400. QueueTestSingleBus::Handler* m_singleHandler = nullptr;
  1401. QueueTestMultiBus::BusPtr m_multiPtr = nullptr;
  1402. void QueueMessage()
  1403. {
  1404. QueueTestMultiBus::QueueEvent(0, &QueueTestMultiBus::Events::OnMessage);
  1405. QueueTestSingleBus::QueueBroadcast(&QueueTestSingleBus::Events::OnMessage);
  1406. }
  1407. void QueueMessagePtr()
  1408. {
  1409. QueueTestMultiBus::QueueEvent(m_multiPtr, &QueueTestMultiBus::Events::OnMessage);
  1410. QueueTestSingleBus::QueueBroadcast(&QueueTestSingleBus::Events::OnMessage);
  1411. }
  1412. }
  1413. TEST_F(EBus, QueueMessage)
  1414. {
  1415. using namespace QueueMessageTest;
  1416. // Setup
  1417. JobManagerDesc jobDesc;
  1418. JobManagerThreadDesc threadDesc;
  1419. jobDesc.m_workerThreads.push_back(threadDesc);
  1420. jobDesc.m_workerThreads.push_back(threadDesc);
  1421. jobDesc.m_workerThreads.push_back(threadDesc);
  1422. m_jobManager = aznew JobManager(jobDesc);
  1423. m_jobContext = aznew JobContext(*m_jobManager);
  1424. JobContext::SetGlobalContext(m_jobContext);
  1425. m_multiHandler = new QueueTestMultiBus::Handler();
  1426. m_singleHandler = new QueueTestSingleBus::Handler();
  1427. m_singleHandler->m_callCount = 0;
  1428. m_multiHandler->m_callCount = 0;
  1429. const int NumCalls = 5000;
  1430. QueueTestMultiBus::Bind(m_multiPtr, 0);
  1431. m_multiHandler->BusConnect(0);
  1432. m_singleHandler->BusConnect();
  1433. for (int i = 0; i < NumCalls; ++i)
  1434. {
  1435. Job* job = CreateJobFunction(&QueueMessageTest::QueueMessage, true);
  1436. job->Start();
  1437. job = CreateJobFunction(&QueueMessageTest::QueueMessagePtr, true);
  1438. job->Start();
  1439. }
  1440. while (m_singleHandler->m_callCount < NumCalls * 2 || m_multiHandler->m_callCount < NumCalls * 2)
  1441. {
  1442. QueueTestMultiBus::ExecuteQueuedEvents();
  1443. QueueTestSingleBus::ExecuteQueuedEvents();
  1444. AZStd::this_thread::yield();
  1445. }
  1446. // use queuing generic functions to disconnect from the bus
  1447. // the same as m_singleHandler.BusDisconnect(); but delayed until QueueTestSingleBus::ExecuteQueuedEvents()
  1448. QueueTestSingleBus::QueueFunction(&QueueTestSingleBus::Handler::BusDisconnect, m_singleHandler);
  1449. // the same as m_multiHandler.BusDisconnect(); but dalayed until QueueTestMultiBus::ExecuteQueuedEvents();
  1450. QueueTestMultiBus::QueueFunction(static_cast<void(QueueTestMultiBus::Handler::*)()>(&QueueTestMultiBus::Handler::BusDisconnect), m_multiHandler);
  1451. EXPECT_EQ(1, QueueTestSingleBus::GetTotalNumOfEventHandlers());
  1452. EXPECT_EQ(1, QueueTestMultiBus::GetTotalNumOfEventHandlers());
  1453. QueueTestSingleBus::ExecuteQueuedEvents();
  1454. QueueTestMultiBus::ExecuteQueuedEvents();
  1455. EXPECT_EQ(0, QueueTestSingleBus::GetTotalNumOfEventHandlers());
  1456. EXPECT_EQ(0, QueueTestMultiBus::GetTotalNumOfEventHandlers());
  1457. // Cleanup
  1458. delete m_singleHandler;
  1459. delete m_multiHandler;
  1460. m_multiPtr = nullptr;
  1461. JobContext::SetGlobalContext(nullptr);
  1462. delete m_jobContext;
  1463. delete m_jobManager;
  1464. }
  1465. class QueueEbusTest
  1466. : public LeakDetectionFixture
  1467. {
  1468. };
  1469. TEST_F(QueueEbusTest, QueueMessageNoQueueing_QueueMessage_Warning)
  1470. {
  1471. using namespace QueueMessageTest;
  1472. {
  1473. AZ::Test::AssertAbsorber assertAbsorber;
  1474. QueueMessage();
  1475. EXPECT_EQ(assertAbsorber.m_warningCount, 0);
  1476. }
  1477. QueueTestSingleBus::ExecuteQueuedEvents();
  1478. QueueTestSingleBus::AllowFunctionQueuing(false);
  1479. {
  1480. AZ::Test::AssertAbsorber assertAbsorber;
  1481. QueueMessage();
  1482. EXPECT_EQ(assertAbsorber.m_warningCount, 1);
  1483. }
  1484. QueueTestMultiBus::ExecuteQueuedEvents();
  1485. QueueTestSingleBus::AllowFunctionQueuing(true);
  1486. }
  1487. class ConnectDisconnectInterface
  1488. : public EBusTraits
  1489. {
  1490. public:
  1491. virtual ~ConnectDisconnectInterface() {}
  1492. virtual void OnConnectChild() = 0;
  1493. virtual void OnDisconnectMe() = 0;
  1494. virtual void OnDisconnectAll() = 0;
  1495. };
  1496. typedef AZ::EBus<ConnectDisconnectInterface> ConnectDisconnectBus;
  1497. class ConnectDisconnectHandler
  1498. : public ConnectDisconnectBus::Handler
  1499. {
  1500. ConnectDisconnectHandler* m_child;
  1501. public:
  1502. ConnectDisconnectHandler(ConnectDisconnectHandler* child)
  1503. : m_child(child)
  1504. {
  1505. s_handlers.push_back(this);
  1506. if (child != nullptr) // if we are the child don't connect yet
  1507. {
  1508. BusConnect();
  1509. }
  1510. }
  1511. ~ConnectDisconnectHandler() override
  1512. {
  1513. s_handlers.erase(AZStd::find(s_handlers.begin(), s_handlers.end(), this));
  1514. }
  1515. void OnConnectChild() override
  1516. {
  1517. if (m_child)
  1518. {
  1519. m_child->BusConnect();
  1520. }
  1521. }
  1522. void OnDisconnectMe() override
  1523. {
  1524. BusDisconnect();
  1525. }
  1526. void OnDisconnectAll() override
  1527. {
  1528. for (size_t i = 0; i < s_handlers.size(); ++i)
  1529. {
  1530. s_handlers[i]->BusDisconnect();
  1531. }
  1532. }
  1533. static AZStd::fixed_vector<ConnectDisconnectHandler*, 5> s_handlers;
  1534. };
  1535. AZStd::fixed_vector<ConnectDisconnectHandler*, 5> ConnectDisconnectHandler::s_handlers;
  1536. class ConnectDisconnectIdOrderedInterface
  1537. : public EBusTraits
  1538. {
  1539. public:
  1540. //////////////////////////////////////////////////////////////////////////
  1541. // EBus interface settings
  1542. static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::MultipleAndOrdered;
  1543. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  1544. typedef int BusIdType;
  1545. //////////////////////////////////////////////////////////////////////////
  1546. ConnectDisconnectIdOrderedInterface()
  1547. : m_order(0) {}
  1548. virtual ~ConnectDisconnectIdOrderedInterface() {}
  1549. virtual void OnConnectChild() = 0;
  1550. virtual void OnDisconnectMe() = 0;
  1551. virtual void OnDisconnectAll(int busId) = 0;
  1552. virtual bool Compare(const ConnectDisconnectIdOrderedInterface* rhs) const { return m_order < rhs->m_order; }
  1553. int m_order;
  1554. };
  1555. typedef AZ::EBus<ConnectDisconnectIdOrderedInterface> ConnectDisconnectIdOrderedBus;
  1556. class ConnectDisconnectIdOrderedHandler
  1557. : public ConnectDisconnectIdOrderedBus::Handler
  1558. {
  1559. public:
  1560. ConnectDisconnectIdOrderedHandler(int id, int order, ConnectDisconnectIdOrderedHandler* child)
  1561. : ConnectDisconnectIdOrderedBus::Handler()
  1562. , m_child(child)
  1563. , m_busId(id)
  1564. {
  1565. m_order = order;
  1566. s_handlers.push_back(this);
  1567. if (child != nullptr) // if we are the child don't connect yet
  1568. {
  1569. BusConnect(m_busId);
  1570. }
  1571. }
  1572. ~ConnectDisconnectIdOrderedHandler() override
  1573. {
  1574. s_handlers.erase(AZStd::find(s_handlers.begin(), s_handlers.end(), this));
  1575. }
  1576. void OnConnectChild() override
  1577. {
  1578. if (m_child)
  1579. {
  1580. m_child->BusConnect(m_busId);
  1581. }
  1582. }
  1583. void OnDisconnectMe() override
  1584. {
  1585. BusDisconnect();
  1586. }
  1587. void OnDisconnectAll(int busId) override
  1588. {
  1589. for (size_t i = 0; i < s_handlers.size(); ++i)
  1590. {
  1591. if (busId == -1 || busId == s_handlers[i]->m_busId)
  1592. {
  1593. s_handlers[i]->BusDisconnect();
  1594. }
  1595. }
  1596. }
  1597. static AZStd::fixed_vector<ConnectDisconnectIdOrderedHandler*, 5> s_handlers;
  1598. protected:
  1599. ConnectDisconnectIdOrderedHandler* m_child;
  1600. int m_busId;
  1601. };
  1602. AZStd::fixed_vector<ConnectDisconnectIdOrderedHandler*, 5> ConnectDisconnectIdOrderedHandler::s_handlers;
  1603. /**
  1604. * Tests a bus when we allow to disconnect while executing messages.
  1605. */
  1606. TEST_F(EBus, DisconnectInDispatch)
  1607. {
  1608. ConnectDisconnectHandler child(nullptr);
  1609. EXPECT_EQ(0, ConnectDisconnectBus::GetTotalNumOfEventHandlers());
  1610. ConnectDisconnectHandler l(&child);
  1611. EXPECT_EQ(1, ConnectDisconnectBus::GetTotalNumOfEventHandlers());
  1612. // Test connect in the during the message call
  1613. ConnectDisconnectBus::Broadcast(&ConnectDisconnectBus::Events::OnConnectChild); // connect the child object
  1614. EXPECT_EQ(2, ConnectDisconnectBus::GetTotalNumOfEventHandlers());
  1615. ConnectDisconnectBus::Broadcast(&ConnectDisconnectBus::Events::OnDisconnectAll); // Disconnect all members during a message
  1616. EXPECT_EQ(0, ConnectDisconnectBus::GetTotalNumOfEventHandlers());
  1617. ConnectDisconnectIdOrderedHandler ch10(10, 1, nullptr);
  1618. ConnectDisconnectIdOrderedHandler ch5(5, 20, nullptr);
  1619. EXPECT_EQ(0, ConnectDisconnectIdOrderedBus::GetTotalNumOfEventHandlers());
  1620. ConnectDisconnectIdOrderedHandler pa10(10, 10, &ch10);
  1621. ConnectDisconnectIdOrderedHandler pa20(20, 20, &ch5);
  1622. EXPECT_EQ(2, ConnectDisconnectIdOrderedBus::GetTotalNumOfEventHandlers());
  1623. ConnectDisconnectIdOrderedBus::Broadcast(&ConnectDisconnectIdOrderedBus::Events::OnConnectChild); // connect the child object
  1624. EXPECT_EQ(4, ConnectDisconnectIdOrderedBus::GetTotalNumOfEventHandlers());
  1625. // Disconnect all members from bus 10 (it will be sorted first)
  1626. // This we we can test a bus removal while traversing
  1627. ConnectDisconnectIdOrderedBus::Broadcast(&ConnectDisconnectIdOrderedBus::Events::OnDisconnectAll, 10);
  1628. EXPECT_EQ(2, ConnectDisconnectIdOrderedBus::GetTotalNumOfEventHandlers());
  1629. // Now disconnect all buses
  1630. ConnectDisconnectIdOrderedBus::Broadcast(&ConnectDisconnectIdOrderedBus::Events::OnDisconnectAll, -1);
  1631. EXPECT_EQ(0, ConnectDisconnectIdOrderedBus::GetTotalNumOfEventHandlers());
  1632. }
  1633. class DisconnectNextHandlerInterface
  1634. : public AZ::EBusTraits
  1635. {
  1636. public:
  1637. static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  1638. static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::MultipleAndOrdered;
  1639. using BusIdType = int32_t;
  1640. // Comparison function which always sorts to the end
  1641. struct DisconnectNextHandlerLess
  1642. {
  1643. // Intrusive_multiset requires the first_argument_type parameter for it's comparison function, but it is deprecated in C++17
  1644. // This should be removed when C++17 support is added
  1645. using first_argument_type = DisconnectNextHandlerInterface*;
  1646. constexpr bool operator()(const DisconnectNextHandlerInterface*, const DisconnectNextHandlerInterface*) const
  1647. {
  1648. return false;
  1649. }
  1650. };
  1651. using BusHandlerOrderCompare = DisconnectNextHandlerLess;
  1652. virtual void DisconnectNextHandler() = 0;
  1653. };
  1654. using DisconnectNextHandlerBus = AZ::EBus<DisconnectNextHandlerInterface>;
  1655. class DisconnectNextHandlerByIdImpl
  1656. : public DisconnectNextHandlerBus::MultiHandler
  1657. {
  1658. public:
  1659. void DisconnectNextHandler() override
  1660. {
  1661. if (m_nextHandler)
  1662. {
  1663. m_nextHandler->BusDisconnect(*DisconnectNextHandlerBus::GetCurrentBusId());
  1664. ++m_handlerDisconnectCounter;
  1665. }
  1666. }
  1667. static constexpr int32_t firstBusAddress = 1;
  1668. static constexpr int32_t secondBusAddress = 2;
  1669. DisconnectNextHandlerByIdImpl* m_nextHandler{};
  1670. int32_t m_handlerDisconnectCounter{};
  1671. };
  1672. constexpr int32_t DisconnectNextHandlerByIdImpl::firstBusAddress;
  1673. constexpr int32_t DisconnectNextHandlerByIdImpl::secondBusAddress;
  1674. /**
  1675. * Tests disconnecting the next handler within a bus during a dispatch
  1676. */
  1677. TEST_F(EBus, DisconnectNextHandlerDuringDispatch_DoesNotCrash)
  1678. {
  1679. DisconnectNextHandlerByIdImpl multiHandler1;
  1680. multiHandler1.BusConnect(DisconnectNextHandlerByIdImpl::firstBusAddress);
  1681. multiHandler1.BusConnect(DisconnectNextHandlerByIdImpl::secondBusAddress);
  1682. DisconnectNextHandlerByIdImpl multiHandler2;
  1683. multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::firstBusAddress);
  1684. multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::secondBusAddress);
  1685. // Set the first handler m_nextHandler field to point to the second handler
  1686. multiHandler1.m_nextHandler = &multiHandler2;
  1687. // Disconnect the next handlers from the second bus address to catch any issues with the address hash_table iterators becoming invalidated
  1688. DisconnectNextHandlerBus::Event(DisconnectNextHandlerByIdImpl::secondBusAddress, &DisconnectNextHandlerInterface::DisconnectNextHandler);
  1689. EXPECT_EQ(1, multiHandler1.m_handlerDisconnectCounter);
  1690. EXPECT_EQ(0, multiHandler2.m_handlerDisconnectCounter);
  1691. DisconnectNextHandlerBus::Event(DisconnectNextHandlerByIdImpl::firstBusAddress, &DisconnectNextHandlerInterface::DisconnectNextHandler);
  1692. EXPECT_EQ(2, multiHandler1.m_handlerDisconnectCounter);
  1693. EXPECT_EQ(0, multiHandler2.m_handlerDisconnectCounter);
  1694. }
  1695. class DisconnectNextAddressInterface
  1696. : public AZ::EBusTraits
  1697. {
  1698. public:
  1699. static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ByIdAndOrdered;
  1700. static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
  1701. using BusIdType = int32_t;
  1702. struct BusIdOrderLess
  1703. {
  1704. constexpr bool operator()(BusIdType lhs, BusIdType rhs) const
  1705. {
  1706. return lhs < rhs;
  1707. }
  1708. };
  1709. using BusIdOrderCompare = BusIdOrderLess;
  1710. virtual void DisconnectNextAddress() = 0;
  1711. };
  1712. using DisconnectNextAddressBus = AZ::EBus<DisconnectNextAddressInterface>;
  1713. class DisconnectNextAddressImpl
  1714. : public DisconnectNextAddressBus::Handler
  1715. {
  1716. public:
  1717. void DisconnectNextAddress() override
  1718. {
  1719. if (m_nextAddressHandler)
  1720. {
  1721. m_nextAddressHandler->BusDisconnect();
  1722. ++m_addressDisconnectCounter;
  1723. }
  1724. }
  1725. static constexpr int32_t firstBusAddress = 1;
  1726. static constexpr int32_t nextBusAddress = 2;
  1727. DisconnectNextAddressImpl* m_nextAddressHandler{};
  1728. int32_t m_addressDisconnectCounter{};
  1729. };
  1730. constexpr int32_t DisconnectNextAddressImpl::firstBusAddress;
  1731. constexpr int32_t DisconnectNextAddressImpl::nextBusAddress;
  1732. /**
  1733. * Tests disconnecting the next address within a bus during a dispatch
  1734. */
  1735. TEST_F(EBus, DisconnectNextAddressDuringDispatch_DoesNotCrash)
  1736. {
  1737. DisconnectNextAddressImpl addressHandler1;
  1738. addressHandler1.BusConnect(DisconnectNextAddressImpl::firstBusAddress);
  1739. DisconnectNextAddressImpl addressHandler2;
  1740. addressHandler2.BusConnect(DisconnectNextAddressImpl::nextBusAddress);
  1741. addressHandler1.m_nextAddressHandler = &addressHandler2;
  1742. // Disconnect the second address handler using the first address handler
  1743. DisconnectNextAddressBus::Event(DisconnectNextAddressImpl::firstBusAddress, &DisconnectNextAddressInterface::DisconnectNextAddress);
  1744. EXPECT_EQ(1, addressHandler1.m_addressDisconnectCounter);
  1745. EXPECT_EQ(0, addressHandler2.m_addressDisconnectCounter);
  1746. }
  1747. /**
  1748. * Test multiple handler.
  1749. */
  1750. namespace MultiHandlerTest
  1751. {
  1752. class MyEventGroup
  1753. : public AZ::EBusTraits
  1754. {
  1755. public:
  1756. //////////////////////////////////////////////////////////////////////////
  1757. // EBus Settings
  1758. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  1759. typedef unsigned int BusIdType;
  1760. //////////////////////////////////////////////////////////////////////////
  1761. virtual ~MyEventGroup() {}
  1762. //////////////////////////////////////////////////////////////////////////
  1763. // Define the events in this event group!
  1764. virtual void OnAction() = 0;
  1765. //////////////////////////////////////////////////////////////////////////
  1766. };
  1767. typedef AZ::EBus<MyEventGroup> MyEventBus;
  1768. class MultiHandler
  1769. : public MyEventBus::MultiHandler
  1770. {
  1771. public:
  1772. MultiHandler()
  1773. : m_expectedCurrentId(0)
  1774. , m_numCalls(0)
  1775. {}
  1776. void OnAction() override
  1777. {
  1778. const unsigned int* currentIdPtr = MyEventBus::GetCurrentBusId();
  1779. ASSERT_NE(nullptr, currentIdPtr);
  1780. EXPECT_EQ(*currentIdPtr, m_expectedCurrentId);
  1781. ++m_numCalls;
  1782. }
  1783. unsigned int m_expectedCurrentId;
  1784. unsigned int m_numCalls;
  1785. };
  1786. }
  1787. TEST_F(EBus, MultiHandler)
  1788. {
  1789. using namespace MultiHandlerTest;
  1790. MultiHandler ml;
  1791. ml.BusConnect(10);
  1792. ml.BusConnect(12);
  1793. ml.BusConnect(13);
  1794. // test copy handlers and make sure they attached to the same bus
  1795. MultiHandler mlCopy = ml;
  1796. EXPECT_EQ(0, mlCopy.m_numCalls);
  1797. // Called outside of an even it should always return nullptr
  1798. EXPECT_EQ(nullptr, MyEventBus::GetCurrentBusId());
  1799. MyEventBus::Event(1, &MyEventBus::Events::OnAction); // this should not trigger a call
  1800. EXPECT_EQ(0, ml.m_numCalls);
  1801. // Issues calls which we listen for
  1802. ml.m_expectedCurrentId = 10;
  1803. mlCopy.m_expectedCurrentId = 10;
  1804. MyEventBus::Event(10, &MyEventBus::Events::OnAction);
  1805. EXPECT_EQ(1, ml.m_numCalls);
  1806. EXPECT_EQ(1, mlCopy.m_numCalls); // make sure the handler copy is connected
  1807. mlCopy.BusDisconnect();
  1808. ml.m_expectedCurrentId = 12;
  1809. MyEventBus::Event(12, &MyEventBus::Events::OnAction);
  1810. EXPECT_EQ(2, ml.m_numCalls);
  1811. ml.m_expectedCurrentId = 13;
  1812. MyEventBus::Event(13, &MyEventBus::Events::OnAction);
  1813. EXPECT_EQ(3, ml.m_numCalls);
  1814. }
  1815. // Non intrusive EBusTraits
  1816. struct MyCustomTraits
  1817. : public AZ::EBusTraits
  1818. {
  1819. // ... custom traits here
  1820. };
  1821. /**
  1822. * Interface that we don't own and we can't inherit traits
  1823. */
  1824. class My3rdPartyInterface
  1825. {
  1826. public:
  1827. virtual void SomeEvent(int a) = 0;
  1828. };
  1829. // 3rd party interface (which is compliant with EBus requirements)
  1830. typedef AZ::EBus<My3rdPartyInterface, MyCustomTraits> My3rdPartyBus1;
  1831. // 3rd party interface that we want to wrap
  1832. class My3rdPartyInterfaceWrapped
  1833. : public My3rdPartyInterface
  1834. , public AZ::EBusTraits
  1835. {
  1836. };
  1837. typedef AZ::EBus<My3rdPartyInterfaceWrapped> My3rdPartyBus2;
  1838. // regular interface trough traits inheritance, please look at the all the samples above
  1839. // combine an ebus and an interface, so you don't need any typedefs. You will need to specialize a template so the bus can get it's traits
  1840. // Keep in mind that this type will not allow for interfaces to be extended, but it's ok for final interfaces
  1841. class MyEBusInterface
  1842. : public AZ::EBus<MyEBusInterface, MyCustomTraits>
  1843. {
  1844. public:
  1845. virtual void Event(int a) const = 0;
  1846. };
  1847. /**
  1848. * Test and demonstrate different EBus implementations
  1849. */
  1850. namespace ImplementationTest
  1851. {
  1852. class Handler1
  1853. : public My3rdPartyBus1::Handler
  1854. {
  1855. public:
  1856. Handler1()
  1857. : m_calls(0)
  1858. {
  1859. My3rdPartyBus1::Handler::BusConnect();
  1860. }
  1861. int m_calls;
  1862. private:
  1863. void SomeEvent(int a) override
  1864. {
  1865. (void)a;
  1866. ++m_calls;
  1867. }
  1868. };
  1869. class Handler2
  1870. : public My3rdPartyBus2::Handler
  1871. {
  1872. public:
  1873. Handler2()
  1874. : m_calls(0)
  1875. {
  1876. My3rdPartyBus2::Handler::BusConnect();
  1877. }
  1878. int m_calls;
  1879. private:
  1880. void SomeEvent(int a) override
  1881. {
  1882. (void)a;
  1883. ++m_calls;
  1884. }
  1885. };
  1886. class Handler3
  1887. : public MyEBusInterface::Handler
  1888. {
  1889. public:
  1890. Handler3()
  1891. : m_calls(0)
  1892. {
  1893. MyEBusInterface::Handler::BusConnect();
  1894. }
  1895. mutable int m_calls;
  1896. private:
  1897. void Event(int a) const override
  1898. {
  1899. (void)a;
  1900. ++m_calls;
  1901. }
  1902. };
  1903. }
  1904. TEST_F(EBus, ExternalInterface)
  1905. {
  1906. using namespace ImplementationTest;
  1907. Handler1 h1;
  1908. Handler2 h2;
  1909. Handler3 h3;
  1910. // test copy of handler
  1911. Handler1 h1Copy = h1;
  1912. EXPECT_EQ(0, h1Copy.m_calls);
  1913. My3rdPartyBus1::Broadcast(&My3rdPartyBus1::Events::SomeEvent, 1);
  1914. EXPECT_EQ(1, h1.m_calls);
  1915. EXPECT_EQ(1, h1Copy.m_calls); // check that the copy works too
  1916. My3rdPartyBus2::Broadcast(&My3rdPartyBus2::Events::SomeEvent, 2);
  1917. EXPECT_EQ(1, h2.m_calls);
  1918. MyEBusInterface::Broadcast(&MyEBusInterface::Events::Event, 3);
  1919. EXPECT_EQ(1, h3.m_calls);
  1920. }
  1921. /**
  1922. *
  1923. */
  1924. TEST_F(EBus, Results)
  1925. {
  1926. // Test the result logical aggregator for OR
  1927. {
  1928. AZ::EBusLogicalResult<bool, AZStd::logical_or<bool> > or_false_false(false);
  1929. or_false_false = false;
  1930. or_false_false = false;
  1931. EXPECT_FALSE(or_false_false.value);
  1932. }
  1933. {
  1934. AZ::EBusLogicalResult<bool, AZStd::logical_or<bool> > or_true_false(false);
  1935. or_true_false = true;
  1936. or_true_false = false;
  1937. EXPECT_TRUE(or_true_false.value);
  1938. }
  1939. // Test the result logical aggregator for AND
  1940. {
  1941. AZ::EBusLogicalResult<bool, AZStd::logical_and<bool> > and_true_false(true);
  1942. and_true_false = true;
  1943. and_true_false = false;
  1944. EXPECT_FALSE(and_true_false.value);
  1945. }
  1946. {
  1947. AZ::EBusLogicalResult<bool, AZStd::logical_and<bool> > and_true_true(true);
  1948. and_true_true = true;
  1949. and_true_true = true;
  1950. EXPECT_TRUE(and_true_true.value);
  1951. }
  1952. }
  1953. // Routers, Bridging and Versioning
  1954. /**
  1955. * EBusInterfaceV1, since we want to keep binary compatibility (we don't need to recompile)
  1956. * when we are implementing the version messaging we should not change the V1 EBus, all code
  1957. * should be triggered from the new version that is not compiled is customer's code yet.
  1958. */
  1959. class EBusInterfaceV1 : public AZ::EBusTraits
  1960. {
  1961. public:
  1962. virtual void OnEvent(int a)
  1963. {
  1964. (void)a;
  1965. }
  1966. };
  1967. using EBusVersion1 = AZ::EBus<EBusInterfaceV1>;
  1968. /**
  1969. * Version 2 of the interface which communicates with Version 1 of the bus bidirectionally.
  1970. */
  1971. class EBusInterfaceV2 : public AZ::EBusTraits
  1972. {
  1973. public:
  1974. /**
  1975. * Router policy implementation that bridges two EBuses by default.
  1976. * It this case we use it to implement versioning between V1 and V2
  1977. * of a specific EBus version.
  1978. */
  1979. template<typename Bus>
  1980. struct RouterPolicy : public EBusRouterPolicy<Bus>
  1981. {
  1982. struct V2toV1Router : public Bus::NestedVersionRouter
  1983. {
  1984. void OnEvent(int a, int b) override
  1985. {
  1986. if (!m_policy->m_isOnEventRouting)
  1987. {
  1988. m_policy->m_isOnEventRouting = true;
  1989. this->template ForwardEvent<EBusVersion1>(&EBusVersion1::Events::OnEvent, a + b);
  1990. m_policy->m_isOnEventRouting = false;
  1991. }
  1992. }
  1993. typename Bus::RouterPolicy* m_policy = nullptr;
  1994. };
  1995. struct V1toV2Router : public EBusVersion1::Router
  1996. {
  1997. void OnEvent(int a) override
  1998. {
  1999. if(!m_policy->m_isOnEventRouting)
  2000. {
  2001. m_policy->m_isOnEventRouting = true;
  2002. this->template ForwardEvent<Bus>(&Bus::Events::OnEvent, a, 0);
  2003. m_policy->m_isOnEventRouting = false;
  2004. }
  2005. }
  2006. typename Bus::RouterPolicy* m_policy = nullptr;
  2007. };
  2008. RouterPolicy()
  2009. {
  2010. m_v2toV1Router.m_policy = this;
  2011. m_v1toV2Router.m_policy = this;
  2012. m_v2toV1Router.BusRouterConnect(this->m_routers);
  2013. m_v1toV2Router.BusRouterConnect();
  2014. }
  2015. ~RouterPolicy()
  2016. {
  2017. m_v2toV1Router.BusRouterDisconnect(this->m_routers);
  2018. m_v1toV2Router.BusRouterDisconnect();
  2019. }
  2020. // State of current routed events to avoid loopbacks
  2021. // this is NOT needed if we route only one way V2->V1 or V1->V2
  2022. bool m_isOnEventRouting = false;
  2023. // Possible optimization, When we are dealing with version we usually don't expect to have active use of the old version,
  2024. // it's just for compatibility. Having routers trying to route to old version busses that rarely
  2025. // have listeners will have it's overhead. To reduct that we can add m_onDemandRouters list that
  2026. // have a pointer to a router and oder, so we can automatically connect that router only when
  2027. // listeners are attached to the old version of the bus. We are talking only about NewVersion->OldVersion
  2028. // bridge (the opposite can be always connected as the overhead will be on the OldVersion bus which we don't expect to use much anyway).
  2029. V2toV1Router m_v2toV1Router;
  2030. V1toV2Router m_v1toV2Router;
  2031. };
  2032. virtual void OnEvent(int a, int b) { (void)a; (void)b; }
  2033. };
  2034. using EBusVersion2 = AZ::EBus<EBusInterfaceV2>;
  2035. namespace RoutingTest
  2036. {
  2037. class EBusInterceptor : public EBusVersion1::Router
  2038. {
  2039. public:
  2040. void OnEvent(int a) override
  2041. {
  2042. EXPECT_EQ(1020, a);
  2043. m_numOnEvent++;
  2044. }
  2045. int m_numOnEvent = 0;
  2046. };
  2047. class V1EventRouter : public EBusVersion1::Router
  2048. {
  2049. public:
  2050. void OnEvent(int a) override
  2051. {
  2052. (void)a;
  2053. m_numOnEvent++;
  2054. EBusVersion1::SetRouterProcessingState(m_processingState);
  2055. }
  2056. int m_numOnEvent = 0;
  2057. EBusVersion1::RouterProcessingState m_processingState = EBusVersion1::RouterProcessingState::SkipListeners;
  2058. };
  2059. class EBusVersion1Handler : public EBusVersion1::Handler
  2060. {
  2061. public:
  2062. void OnEvent(int a) override
  2063. {
  2064. (void)a;
  2065. m_numOnEvent++;
  2066. }
  2067. int m_numOnEvent = 0;
  2068. };
  2069. class EBusVersion2Handler : public EBusVersion2::Handler
  2070. {
  2071. public:
  2072. void OnEvent(int a, int b) override
  2073. {
  2074. (void)a; (void)b;
  2075. m_numOnEvent++;
  2076. }
  2077. int m_numOnEvent = 0;
  2078. };
  2079. }
  2080. #if !AZ_TRAIT_DISABLE_FAILED_EBUS_ROUTING_TEST
  2081. TEST_F(EBus, Routing)
  2082. {
  2083. using namespace RoutingTest;
  2084. EBusInterceptor interceptor;
  2085. EBusVersion1Handler v1Handler;
  2086. v1Handler.BusConnect();
  2087. interceptor.BusRouterConnect();
  2088. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
  2089. EXPECT_EQ(1, interceptor.m_numOnEvent);
  2090. EXPECT_EQ(1, v1Handler.m_numOnEvent);
  2091. interceptor.BusRouterDisconnect();
  2092. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
  2093. EXPECT_EQ(1, interceptor.m_numOnEvent);
  2094. EXPECT_EQ(2, v1Handler.m_numOnEvent);
  2095. // routing events
  2096. {
  2097. // reset counter
  2098. v1Handler.m_numOnEvent = 0;
  2099. V1EventRouter v1Router;
  2100. v1Router.BusRouterConnect();
  2101. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
  2102. EXPECT_EQ(1, v1Router.m_numOnEvent);
  2103. EXPECT_EQ(0, v1Handler.m_numOnEvent);
  2104. v1Router.BusRouterDisconnect();
  2105. }
  2106. // routing events and skipping further routing
  2107. {
  2108. // reset counter
  2109. v1Handler.m_numOnEvent = 0;
  2110. V1EventRouter v1RouterFirst, v1RouterSecond;
  2111. v1RouterFirst.BusRouterConnect(-1);
  2112. v1RouterSecond.BusRouterConnect();
  2113. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
  2114. EXPECT_EQ(1, v1RouterFirst.m_numOnEvent);
  2115. EXPECT_EQ(1, v1RouterSecond.m_numOnEvent);
  2116. EXPECT_EQ(0, v1Handler.m_numOnEvent);
  2117. // now instruct router 1 to block any further event processing
  2118. v1RouterFirst.m_processingState = EBusVersion1::RouterProcessingState::SkipListenersAndRouters;
  2119. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 1020);
  2120. EXPECT_EQ(2, v1RouterFirst.m_numOnEvent);
  2121. EXPECT_EQ(1, v1RouterSecond.m_numOnEvent);
  2122. EXPECT_EQ(0, v1Handler.m_numOnEvent);
  2123. }
  2124. // test bridging two EBus by using routers. This can be used to handle different bus versions.
  2125. {
  2126. EBusVersion2Handler v2Handler;
  2127. v2Handler.BusConnect();
  2128. // reset counter
  2129. v1Handler.m_numOnEvent = 0;
  2130. EBusVersion2::Broadcast(&EBusVersion2::Events::OnEvent, 10, 20);
  2131. EXPECT_EQ(1, v1Handler.m_numOnEvent);
  2132. EXPECT_EQ(1, v2Handler.m_numOnEvent);
  2133. EBusVersion1::Broadcast(&EBusVersion1::Events::OnEvent, 30);
  2134. EXPECT_EQ(2, v1Handler.m_numOnEvent);
  2135. EXPECT_EQ(2, v2Handler.m_numOnEvent);
  2136. }
  2137. // We can test Queue and Event routing separately,
  2138. // however they do use the same code path (as we don't queue routing and we just use the ID to differentiate between Broadcast and Event)
  2139. }
  2140. #endif // !AZ_TRAIT_DISABLE_FAILED_EBUS_ROUTING_TEST
  2141. struct LocklessEvents
  2142. : public AZ::EBusTraits
  2143. {
  2144. using MutexType = AZStd::mutex;
  2145. static const bool LocklessDispatch = true;
  2146. virtual ~LocklessEvents() = default;
  2147. virtual void RemoveMe() = 0;
  2148. virtual void DeleteMe() = 0;
  2149. virtual void Calculate(int x, int y, int z) = 0;
  2150. };
  2151. using LocklessBus = AZ::EBus<LocklessEvents>;
  2152. struct LocklessImpl
  2153. : public LocklessBus::Handler
  2154. {
  2155. uint32_t m_val;
  2156. uint32_t m_maxSleep;
  2157. LocklessImpl(uint32_t maxSleep = 0)
  2158. : m_val(0)
  2159. , m_maxSleep(maxSleep)
  2160. {
  2161. BusConnect();
  2162. }
  2163. ~LocklessImpl() override
  2164. {
  2165. BusDisconnect();
  2166. }
  2167. void RemoveMe() override
  2168. {
  2169. BusDisconnect();
  2170. }
  2171. void DeleteMe() override
  2172. {
  2173. delete this;
  2174. }
  2175. void Calculate(int x, int y, int z) override
  2176. {
  2177. m_val = x + (y * z);
  2178. if (m_maxSleep)
  2179. {
  2180. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(m_val % m_maxSleep));
  2181. }
  2182. }
  2183. };
  2184. void ThrashLocklessDispatch(uint32_t maxSleep = 0)
  2185. {
  2186. const size_t threadCount = 8;
  2187. enum : size_t { cycleCount = 1000 };
  2188. AZStd::thread threads[threadCount];
  2189. AZStd::vector<int> results[threadCount];
  2190. LocklessImpl handler(maxSleep);
  2191. auto work = [maxSleep]()
  2192. {
  2193. char sentinel[64] = { 0 };
  2194. char* end = sentinel + AZ_ARRAY_SIZE(sentinel);
  2195. for (int i = 1; i < cycleCount; ++i)
  2196. {
  2197. // Calculate() already includes a modulo-cycled sleep, add more random jitter
  2198. uint32_t extraSleep_us = maxSleep ? rand() % maxSleep : 0;
  2199. if (extraSleep_us % 3)
  2200. {
  2201. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(extraSleep_us));
  2202. }
  2203. LocklessBus::Broadcast(&LocklessBus::Events::Calculate, i, i * 2, i << 4);
  2204. bool failed = (AZStd::find_if(&sentinel[0], end, [](char s) { return s != 0; }) != end);
  2205. EXPECT_FALSE(failed);
  2206. }
  2207. };
  2208. for (AZStd::thread& thread : threads)
  2209. {
  2210. thread = AZStd::thread(work);
  2211. }
  2212. for (AZStd::thread& thread : threads)
  2213. {
  2214. thread.join();
  2215. }
  2216. }
  2217. TEST_F(EBus, ThrashLocklessDispatchYOLO)
  2218. {
  2219. ThrashLocklessDispatch();
  2220. }
  2221. TEST_F(EBus, ThrashLocklessDispatchSimulateWork)
  2222. {
  2223. ThrashLocklessDispatch(4);
  2224. }
  2225. TEST_F(EBus, DisconnectInLocklessDispatch)
  2226. {
  2227. LocklessImpl handler;
  2228. AZ_TEST_START_TRACE_SUPPRESSION;
  2229. LocklessBus::Broadcast(&LocklessBus::Events::RemoveMe);
  2230. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  2231. }
  2232. TEST_F(EBus, DeleteInLocklessDispatch)
  2233. {
  2234. LocklessImpl* handler = new LocklessImpl();
  2235. AZ_UNUSED(handler);
  2236. AZ_TEST_START_TRACE_SUPPRESSION;
  2237. LocklessBus::Broadcast(&LocklessBus::Events::DeleteMe);
  2238. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  2239. }
  2240. namespace LocklessTest
  2241. {
  2242. struct LocklessConnectorEvents
  2243. : public AZ::EBusTraits
  2244. {
  2245. using MutexType = AZStd::recursive_mutex;
  2246. static const bool LocklessDispatch = true;
  2247. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  2248. typedef uint32_t BusIdType;
  2249. virtual ~LocklessConnectorEvents() = default;
  2250. virtual void DoConnect() = 0;
  2251. virtual void DoDisconnect() = 0;
  2252. };
  2253. using LocklessConnectorBus = AZ::EBus<LocklessConnectorEvents>;
  2254. class MyEventGroup
  2255. : public AZ::EBusTraits
  2256. {
  2257. public:
  2258. using MutexType = AZStd::recursive_mutex;
  2259. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  2260. typedef uint32_t BusIdType;
  2261. virtual void Calculate(int x, int y, int z) = 0;
  2262. virtual ~MyEventGroup() {}
  2263. };
  2264. using MyEventGroupBus = AZ::EBus< MyEventGroup >;
  2265. struct DoubleEbusImpl
  2266. : public LocklessConnectorBus::Handler,
  2267. MyEventGroupBus::Handler
  2268. {
  2269. uint32_t m_id;
  2270. uint32_t m_val;
  2271. uint32_t m_maxSleep;
  2272. DoubleEbusImpl(uint32_t id, uint32_t maxSleep)
  2273. : m_id(id)
  2274. , m_val(0)
  2275. , m_maxSleep(maxSleep)
  2276. {
  2277. LocklessConnectorBus::Handler::BusConnect(m_id);
  2278. }
  2279. ~DoubleEbusImpl() override
  2280. {
  2281. MyEventGroupBus::Handler::BusDisconnect();
  2282. LocklessConnectorBus::Handler::BusDisconnect();
  2283. }
  2284. void Calculate(int x, int y, int z) override
  2285. {
  2286. m_val = x + (y * z);
  2287. if (m_maxSleep)
  2288. {
  2289. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(m_val % m_maxSleep));
  2290. }
  2291. }
  2292. void DoConnect() override
  2293. {
  2294. MyEventGroupBus::Handler::BusConnect(m_id);
  2295. }
  2296. void DoDisconnect() override
  2297. {
  2298. MyEventGroupBus::Handler::BusDisconnect();
  2299. }
  2300. };
  2301. }
  2302. TEST_F(EBus, MixedLocklessTest)
  2303. {
  2304. using namespace LocklessTest;
  2305. const int maxSleep = 5;
  2306. const size_t threadCount = 8;
  2307. enum : size_t { cycleCount = 500 };
  2308. AZStd::thread threads[threadCount];
  2309. AZStd::vector<int> results[threadCount];
  2310. AZStd::vector<DoubleEbusImpl> handlerList;
  2311. for (int i = 0; i < threadCount; i++)
  2312. {
  2313. handlerList.emplace_back(i, maxSleep);
  2314. }
  2315. auto work = []()
  2316. {
  2317. char sentinel[64] = { 0 };
  2318. char* end = sentinel + AZ_ARRAY_SIZE(sentinel);
  2319. for (int i = 1; i < cycleCount; ++i)
  2320. {
  2321. uint32_t id = rand() % threadCount;
  2322. LocklessConnectorBus::Event(id, &LocklessConnectorBus::Events::DoConnect);
  2323. // Calculate() already includes a modulo-cycled sleep, add more random jitter
  2324. uint32_t extraSleep_us = maxSleep ? rand() % maxSleep : 0;
  2325. if (extraSleep_us % 3)
  2326. {
  2327. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(extraSleep_us));
  2328. }
  2329. MyEventGroupBus::Event(id, &MyEventGroupBus::Events::Calculate, i, i * 2, i << 4);
  2330. LocklessConnectorBus::Event(id, &LocklessConnectorBus::Events::DoDisconnect);
  2331. bool failed = (AZStd::find_if(&sentinel[0], end, [](char s) { return s != 0; }) != end);
  2332. EXPECT_FALSE(failed) << "sentinel memory unexpectedly tampered with while handling EBus events";
  2333. }
  2334. };
  2335. for (AZStd::thread& thread : threads)
  2336. {
  2337. thread = AZStd::thread(work);
  2338. }
  2339. for (AZStd::thread& thread : threads)
  2340. {
  2341. thread.join();
  2342. }
  2343. }
  2344. namespace MultithreadConnect
  2345. {
  2346. class MyEventGroup
  2347. : public AZ::EBusTraits
  2348. {
  2349. public:
  2350. using MutexType = AZStd::recursive_mutex;
  2351. virtual ~MyEventGroup() {}
  2352. };
  2353. typedef AZ::EBus< MyEventGroup > MyEventGroupBus;
  2354. struct MyEventGroupImpl :
  2355. MyEventGroupBus::Handler
  2356. {
  2357. MyEventGroupImpl()
  2358. {
  2359. }
  2360. ~MyEventGroupImpl() override
  2361. {
  2362. MyEventGroupBus::Handler::BusDisconnect();
  2363. }
  2364. virtual void DoConnect()
  2365. {
  2366. MyEventGroupBus::Handler::BusConnect();
  2367. }
  2368. virtual void DoDisconnect()
  2369. {
  2370. MyEventGroupBus::Handler::BusDisconnect();
  2371. }
  2372. };
  2373. }
  2374. TEST_F(EBus, MultithreadConnectTest)
  2375. {
  2376. using namespace MultithreadConnect;
  2377. const int maxSleep = 5;
  2378. const size_t threadCount = 8;
  2379. enum : size_t { cycleCount = 1000 };
  2380. AZStd::thread threads[threadCount];
  2381. AZStd::vector<int> results[threadCount];
  2382. MyEventGroupImpl handler;
  2383. auto work = [&handler]()
  2384. {
  2385. for (int i = 1; i < cycleCount; ++i)
  2386. {
  2387. handler.DoConnect();
  2388. // add random jitter
  2389. uint32_t extraSleep_us = maxSleep ? rand() % maxSleep : 0;
  2390. if (extraSleep_us % 3)
  2391. {
  2392. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(extraSleep_us));
  2393. }
  2394. handler.DoDisconnect();
  2395. }
  2396. };
  2397. for (AZStd::thread& thread : threads)
  2398. {
  2399. thread = AZStd::thread(work);
  2400. }
  2401. for (AZStd::thread& thread : threads)
  2402. {
  2403. thread.join();
  2404. }
  2405. }
  2406. struct LocklessNullMutexEvents
  2407. : public AZ::EBusTraits
  2408. {
  2409. using MutexType = AZ::NullMutex;
  2410. static const bool LocklessDispatch = true;
  2411. virtual ~LocklessNullMutexEvents() = default;
  2412. virtual void AtomicIncrement() = 0;
  2413. };
  2414. using LocklessNullMutexBus = AZ::EBus<LocklessNullMutexEvents>;
  2415. struct LocklessNullMutexImpl
  2416. : public LocklessNullMutexBus::Handler
  2417. {
  2418. AZStd::atomic<uint64_t> m_val{};
  2419. LocklessNullMutexImpl()
  2420. {
  2421. BusConnect();
  2422. }
  2423. ~LocklessNullMutexImpl() override
  2424. {
  2425. BusDisconnect();
  2426. }
  2427. void AtomicIncrement() override
  2428. {
  2429. ++m_val;
  2430. }
  2431. };
  2432. void ThrashLocklessDispatchNullMutex()
  2433. {
  2434. constexpr size_t threadCount = 8;
  2435. enum : size_t { cycleCount = 1000 };
  2436. constexpr uint64_t expectedAtomicCount = threadCount * cycleCount;
  2437. AZStd::thread threads[threadCount];
  2438. LocklessNullMutexImpl handler;
  2439. auto work = []()
  2440. {
  2441. for (int i = 0; i < cycleCount; ++i)
  2442. {
  2443. // add random jitter
  2444. constexpr int maxSleep = 3;
  2445. uint32_t extraSleep_us = rand() % maxSleep;
  2446. if (extraSleep_us != 0)
  2447. {
  2448. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(extraSleep_us));
  2449. }
  2450. LocklessNullMutexBus::Broadcast(&LocklessNullMutexBus::Events::AtomicIncrement);
  2451. }
  2452. };
  2453. for (AZStd::thread& thread : threads)
  2454. {
  2455. thread = AZStd::thread(work);
  2456. }
  2457. for (AZStd::thread& thread : threads)
  2458. {
  2459. thread.join();
  2460. }
  2461. EXPECT_EQ(expectedAtomicCount, static_cast<uint64_t>(handler.m_val));
  2462. }
  2463. TEST_F(EBus, LocklessDispatchWithNullMutex_Multithread_Thrash)
  2464. {
  2465. ThrashLocklessDispatchNullMutex();
  2466. }
  2467. namespace EBusResultsTest
  2468. {
  2469. class ResultClass
  2470. {
  2471. public:
  2472. int m_value1 = 0;
  2473. int m_value2 = 0;
  2474. bool m_operator_called_const = false;
  2475. bool m_operator_called_rvalue_ref = false;
  2476. ResultClass() = default;
  2477. ResultClass(const ResultClass&) = default;
  2478. bool operator==(const ResultClass& b) const
  2479. {
  2480. return m_value1 == b.m_value1 && m_value2 == b.m_value2;
  2481. }
  2482. ResultClass& operator=(const ResultClass& b)
  2483. {
  2484. m_value1 = b.m_value1 + m_value1;
  2485. m_value2 = b.m_value2 + m_value2;
  2486. m_operator_called_const = true;
  2487. m_operator_called_rvalue_ref = b.m_operator_called_rvalue_ref;
  2488. return *this;
  2489. }
  2490. ResultClass& operator=(ResultClass&& b)
  2491. {
  2492. // combine together to prove its not just an assignment
  2493. m_value1 = b.m_value1 + m_value1;
  2494. m_value2 = b.m_value2 + m_value2;
  2495. // but destroy the original value (emulating move op)
  2496. b.m_value1 = 0;
  2497. b.m_value2 = 0;
  2498. m_operator_called_rvalue_ref = true;
  2499. m_operator_called_const = b.m_operator_called_const;
  2500. return *this;
  2501. }
  2502. };
  2503. class ResultReducerClass
  2504. {
  2505. public:
  2506. bool m_operator_called_const = false;
  2507. bool m_operator_called_rvalue_ref = false;
  2508. ResultClass operator()(const ResultClass& a, const ResultClass& b)
  2509. {
  2510. ResultClass newValue;
  2511. newValue.m_value1 = a.m_value1 + b.m_value1;
  2512. newValue.m_value2 = a.m_value2 + b.m_value2;
  2513. m_operator_called_const = true;
  2514. return newValue;
  2515. }
  2516. ResultClass operator()(const ResultClass& a, ResultClass&& b)
  2517. {
  2518. m_operator_called_rvalue_ref = true;
  2519. ResultClass newValue;
  2520. newValue.m_value1 = a.m_value1 + b.m_value1;
  2521. newValue.m_value2 = a.m_value2 + b.m_value2;
  2522. return newValue;
  2523. }
  2524. };
  2525. class MyInterface
  2526. {
  2527. public:
  2528. virtual ResultClass EventX() = 0;
  2529. virtual const ResultClass& EventY() = 0;
  2530. };
  2531. using MyInterfaceBus = AZ::EBus<MyInterface, AZ::EBusTraits>;
  2532. class MyListener : public MyInterfaceBus::Handler
  2533. {
  2534. public:
  2535. MyListener(int value1, int value2)
  2536. {
  2537. m_result.m_value1 = value1;
  2538. m_result.m_value2 = value2;
  2539. }
  2540. ~MyListener() override
  2541. {
  2542. }
  2543. ResultClass EventX() override
  2544. {
  2545. return m_result;
  2546. }
  2547. const ResultClass& EventY() override
  2548. {
  2549. return m_result;
  2550. }
  2551. ResultClass m_result;
  2552. };
  2553. } // EBusResultsTest
  2554. TEST_F(EBus, ResultsTest)
  2555. {
  2556. using namespace EBusResultsTest;
  2557. MyListener val1(1, 2);
  2558. MyListener val2(3, 4);
  2559. val1.BusConnect();
  2560. val2.BusConnect();
  2561. {
  2562. ResultClass results;
  2563. MyInterfaceBus::BroadcastResult(results, &MyInterfaceBus::Events::EventX);
  2564. // ensure that the RVALUE-REF op was called:
  2565. EXPECT_FALSE(results.m_operator_called_const);
  2566. EXPECT_TRUE(results.m_operator_called_rvalue_ref);
  2567. EXPECT_EQ(results.m_value1, 4); // 1 + 3
  2568. EXPECT_EQ(results.m_value2, 6); // 2 + 4
  2569. // make sure originals are not destroyed
  2570. EXPECT_EQ(val1.m_result.m_value1, 1);
  2571. EXPECT_EQ(val1.m_result.m_value2, 2);
  2572. EXPECT_EQ(val2.m_result.m_value1, 3);
  2573. EXPECT_EQ(val2.m_result.m_value2, 4);
  2574. }
  2575. {
  2576. ResultClass results;
  2577. MyInterfaceBus::BroadcastResult(results, &MyInterfaceBus::Events::EventY);
  2578. // ensure that the const version of operator= was called.
  2579. EXPECT_TRUE(results.m_operator_called_const);
  2580. EXPECT_FALSE(results.m_operator_called_rvalue_ref);
  2581. EXPECT_EQ(results.m_value1, 4); // 1 + 3
  2582. EXPECT_EQ(results.m_value2, 6); // 2 + 4
  2583. // make sure originals are not destroyed
  2584. EXPECT_EQ(val1.m_result.m_value1, 1);
  2585. EXPECT_EQ(val1.m_result.m_value2, 2);
  2586. EXPECT_EQ(val2.m_result.m_value1, 3);
  2587. EXPECT_EQ(val2.m_result.m_value2, 4);
  2588. }
  2589. val1.BusDisconnect();
  2590. val2.BusDisconnect();
  2591. }
  2592. // ensure RVALUE-REF move on RHS does not corrupt existing values.
  2593. TEST_F(EBus, ResultsTest_ReducerCorruption)
  2594. {
  2595. using namespace EBusResultsTest;
  2596. MyListener val1(1, 2);
  2597. MyListener val2(3, 4);
  2598. val1.BusConnect();
  2599. val2.BusConnect();
  2600. {
  2601. EBusReduceResult<ResultClass, ResultReducerClass> resultreducer;
  2602. MyInterfaceBus::BroadcastResult(resultreducer, &MyInterfaceBus::Events::EventX);
  2603. EXPECT_FALSE(resultreducer.unary.m_operator_called_const);
  2604. EXPECT_TRUE(resultreducer.unary.m_operator_called_rvalue_ref);
  2605. // note that operator= is called TWICE here. one on (val1+val2)
  2606. // because the ebus results is defined as "value = unary(a, b)"
  2607. // and in this case both operator = as well as the unary operate here.
  2608. // meaning that the addition is actually run multiple times
  2609. // once for (a+b) and then again, during value = unary(...) for a second time
  2610. EXPECT_EQ(resultreducer.value.m_value1, 7); // (3 + 1) + 3
  2611. EXPECT_EQ(resultreducer.value.m_value2, 10); // (4 + 2) + 4
  2612. // make sure originals are not destroyed in the move
  2613. EXPECT_EQ(val1.m_result.m_value1, 1);
  2614. EXPECT_EQ(val1.m_result.m_value2, 2);
  2615. EXPECT_EQ(val2.m_result.m_value1, 3);
  2616. EXPECT_EQ(val2.m_result.m_value2, 4);
  2617. }
  2618. {
  2619. EBusReduceResult<ResultClass, ResultReducerClass> resultreducer;
  2620. MyInterfaceBus::BroadcastResult(resultreducer, &MyInterfaceBus::Events::EventY);
  2621. EXPECT_TRUE(resultreducer.unary.m_operator_called_const); // we expect the const version to have been called this time
  2622. EXPECT_FALSE(resultreducer.unary.m_operator_called_rvalue_ref);
  2623. EXPECT_EQ(resultreducer.value.m_value1, 7); // (3 + 1) + 3
  2624. EXPECT_EQ(resultreducer.value.m_value2, 10); // (4 + 2) + 4
  2625. // make sure originals are not destroyed in the move
  2626. EXPECT_EQ(val1.m_result.m_value1, 1);
  2627. EXPECT_EQ(val1.m_result.m_value2, 2);
  2628. EXPECT_EQ(val2.m_result.m_value1, 3);
  2629. EXPECT_EQ(val2.m_result.m_value2, 4);
  2630. }
  2631. val1.BusDisconnect();
  2632. val2.BusDisconnect();
  2633. }
  2634. // ensure RVALUE-REF move on RHS does not corrupt existing values and operates correctly
  2635. // even if the other form is used (where T is T&)
  2636. TEST_F(EBus, ResultsTest_ReducerCorruption_Ref)
  2637. {
  2638. using namespace EBusResultsTest;
  2639. MyListener val1(1, 2);
  2640. MyListener val2(3, 4);
  2641. val1.BusConnect();
  2642. val2.BusConnect();
  2643. {
  2644. ResultClass finalResult;
  2645. EBusReduceResult<ResultClass&, ResultReducerClass> resultreducer(finalResult);
  2646. MyInterfaceBus::BroadcastResult(resultreducer, &MyInterfaceBus::Events::EventX);
  2647. EXPECT_FALSE(resultreducer.unary.m_operator_called_const);
  2648. EXPECT_TRUE(resultreducer.unary.m_operator_called_rvalue_ref);
  2649. EXPECT_FALSE(finalResult.m_operator_called_const);
  2650. EXPECT_TRUE(finalResult.m_operator_called_rvalue_ref);
  2651. EXPECT_EQ(resultreducer.value.m_value1, 7); // (3 + 1) + 3
  2652. EXPECT_EQ(resultreducer.value.m_value2, 10); // (4 + 2) + 4
  2653. // make sure originals are not destroyed in the move
  2654. EXPECT_EQ(val1.m_result.m_value1, 1);
  2655. EXPECT_EQ(val1.m_result.m_value2, 2);
  2656. EXPECT_EQ(val2.m_result.m_value1, 3);
  2657. EXPECT_EQ(val2.m_result.m_value2, 4);
  2658. }
  2659. {
  2660. ResultClass finalResult;
  2661. EBusReduceResult<ResultClass&, ResultReducerClass> resultreducer(finalResult);
  2662. MyInterfaceBus::BroadcastResult(resultreducer, &MyInterfaceBus::Events::EventY);
  2663. EXPECT_TRUE(resultreducer.unary.m_operator_called_const); // EventY is const, so we expect this to have happened again
  2664. EXPECT_FALSE(resultreducer.unary.m_operator_called_rvalue_ref);
  2665. // we still expect the actual finalresult to have been populated via RVALUE REF MOVE
  2666. EXPECT_FALSE(finalResult.m_operator_called_const);
  2667. EXPECT_TRUE(finalResult.m_operator_called_rvalue_ref);
  2668. EXPECT_EQ(resultreducer.value.m_value1, 7); // (3 + 1) + 3
  2669. EXPECT_EQ(resultreducer.value.m_value2, 10); // (4 + 2) + 4
  2670. // make sure originals are not destroyed in the move
  2671. EXPECT_EQ(val1.m_result.m_value1, 1);
  2672. EXPECT_EQ(val1.m_result.m_value2, 2);
  2673. EXPECT_EQ(val2.m_result.m_value1, 3);
  2674. EXPECT_EQ(val2.m_result.m_value2, 4);
  2675. }
  2676. val1.BusDisconnect();
  2677. val2.BusDisconnect();
  2678. }
  2679. // ensure RVALUE-REF move on RHS does not corrupt existing values.
  2680. TEST_F(EBus, ResultsTest_AggregatorCorruption)
  2681. {
  2682. using namespace EBusResultsTest;
  2683. MyListener val1(1, 2);
  2684. MyListener val2(3, 4);
  2685. val1.BusConnect();
  2686. val2.BusConnect();
  2687. {
  2688. EBusAggregateResults<ResultClass> resultarray;
  2689. MyInterfaceBus::BroadcastResult(resultarray, &MyInterfaceBus::Events::EventX);
  2690. EXPECT_EQ(resultarray.values.size(), 2);
  2691. // bus connection is unordered, so we just have to find the two values on it, can't assume they're in same order.
  2692. EXPECT_TRUE(resultarray.values[0] == val1.m_result || resultarray.values[1] == val1.m_result);
  2693. EXPECT_TRUE(resultarray.values[0] == val2.m_result || resultarray.values[1] == val2.m_result);
  2694. if (resultarray.values[0] == val1.m_result)
  2695. {
  2696. EXPECT_EQ(resultarray.values[1], val2.m_result);
  2697. }
  2698. if (resultarray.values[0] == val2.m_result)
  2699. {
  2700. EXPECT_EQ(resultarray.values[1], val1.m_result);
  2701. }
  2702. // make sure originals are not destroyed in the move
  2703. EXPECT_EQ(val1.m_result.m_value1, 1);
  2704. EXPECT_EQ(val1.m_result.m_value2, 2);
  2705. EXPECT_EQ(val2.m_result.m_value1, 3);
  2706. EXPECT_EQ(val2.m_result.m_value2, 4);
  2707. }
  2708. {
  2709. EBusAggregateResults<ResultClass> resultarray;
  2710. MyInterfaceBus::BroadcastResult(resultarray, &MyInterfaceBus::Events::EventY);
  2711. // bus connection is unordered, so we just have to find the two values on it, can't assume they're in same order.
  2712. EXPECT_TRUE(resultarray.values[0] == val1.m_result || resultarray.values[1] == val1.m_result);
  2713. EXPECT_TRUE(resultarray.values[0] == val2.m_result || resultarray.values[1] == val2.m_result);
  2714. if (resultarray.values[0] == val1.m_result)
  2715. {
  2716. EXPECT_EQ(resultarray.values[1], val2.m_result);
  2717. }
  2718. if (resultarray.values[0] == val2.m_result)
  2719. {
  2720. EXPECT_EQ(resultarray.values[1], val1.m_result);
  2721. }
  2722. // make sure originals are not destroyed
  2723. EXPECT_EQ(val1.m_result.m_value1, 1);
  2724. EXPECT_EQ(val1.m_result.m_value2, 2);
  2725. EXPECT_EQ(val2.m_result.m_value1, 3);
  2726. EXPECT_EQ(val2.m_result.m_value2, 4);
  2727. }
  2728. val1.BusDisconnect();
  2729. val2.BusDisconnect();
  2730. }
  2731. namespace EBusEnvironmentTest
  2732. {
  2733. class MyInterface
  2734. {
  2735. public:
  2736. virtual void EventX() = 0;
  2737. };
  2738. using MyInterfaceBus = AZ::EBus<MyInterface, AZ::EBusTraits>;
  2739. class MyInterfaceListener : public MyInterfaceBus::Handler
  2740. {
  2741. public:
  2742. MyInterfaceListener(int environmentId = -1)
  2743. : m_environmentId(environmentId)
  2744. , m_numEventsX(0)
  2745. {
  2746. }
  2747. void EventX() override
  2748. {
  2749. ++m_numEventsX;
  2750. }
  2751. int m_environmentId; ///< EBus environment id. -1 is global, otherwise index in the environment array.
  2752. int m_numEventsX;
  2753. };
  2754. class ParallelSeparateEBusEnvironmentProcessor
  2755. {
  2756. public:
  2757. using JobaToProcessArray = AZStd::vector<ParallelSeparateEBusEnvironmentProcessor, AZ::OSStdAllocator>;
  2758. ParallelSeparateEBusEnvironmentProcessor()
  2759. {
  2760. m_busEvironment = AZ::EBusEnvironment::Create();
  2761. }
  2762. ~ParallelSeparateEBusEnvironmentProcessor()
  2763. {
  2764. AZ::EBusEnvironment::Destroy(m_busEvironment);
  2765. }
  2766. void ProcessSomethingInParallel(size_t jobId)
  2767. {
  2768. m_busEvironment->ActivateOnCurrentThread();
  2769. EXPECT_EQ(0, MyInterfaceBus::GetTotalNumOfEventHandlers()); // If environments are properly separated we should have no listeners!"
  2770. MyInterfaceListener uniqueListener((int)jobId);
  2771. uniqueListener.BusConnect();
  2772. const int numEventsToBroadcast = 100;
  2773. for (int i = 0; i < numEventsToBroadcast; ++i)
  2774. {
  2775. // from now on all EBus calls happen in unique environment
  2776. MyInterfaceBus::Broadcast(&MyInterfaceBus::Events::EventX);
  2777. }
  2778. uniqueListener.BusDisconnect();
  2779. // Test that we have only X num events
  2780. EXPECT_EQ(uniqueListener.m_numEventsX, numEventsToBroadcast); // If environments are properly separated we should get only the events from our environment!
  2781. m_busEvironment->DeactivateOnCurrentThread();
  2782. }
  2783. static void ProcessJobsRange(JobaToProcessArray* jobs, size_t startIndex, size_t endIndex)
  2784. {
  2785. for (size_t i = startIndex; i <= endIndex; ++i)
  2786. {
  2787. (*jobs)[i].ProcessSomethingInParallel(i);
  2788. }
  2789. }
  2790. AZ::EBusEnvironment* m_busEvironment;
  2791. };
  2792. } // EBusEnvironmentTest
  2793. TEST_F(EBus, EBusEnvironment)
  2794. {
  2795. using namespace EBusEnvironmentTest;
  2796. ParallelSeparateEBusEnvironmentProcessor::JobaToProcessArray jobsToProcess;
  2797. jobsToProcess.resize(10000);
  2798. MyInterfaceListener globalListener;
  2799. globalListener.BusConnect();
  2800. // broadcast on global bus
  2801. MyInterfaceBus::Broadcast(&MyInterfaceBus::Events::EventX);
  2802. // spawn a few threads to process those jobs
  2803. AZStd::thread thread1(AZStd::bind(&ParallelSeparateEBusEnvironmentProcessor::ProcessJobsRange, &jobsToProcess, 0, 1999));
  2804. AZStd::thread thread2(AZStd::bind(&ParallelSeparateEBusEnvironmentProcessor::ProcessJobsRange, &jobsToProcess, 2000, 3999));
  2805. AZStd::thread thread3(AZStd::bind(&ParallelSeparateEBusEnvironmentProcessor::ProcessJobsRange, &jobsToProcess, 4000, 5999));
  2806. AZStd::thread thread4(AZStd::bind(&ParallelSeparateEBusEnvironmentProcessor::ProcessJobsRange, &jobsToProcess, 6000, 7999));
  2807. AZStd::thread thread5(AZStd::bind(&ParallelSeparateEBusEnvironmentProcessor::ProcessJobsRange, &jobsToProcess, 8000, 9999));
  2808. thread5.join();
  2809. thread4.join();
  2810. thread3.join();
  2811. thread2.join();
  2812. thread1.join();
  2813. globalListener.BusDisconnect();
  2814. EXPECT_EQ(1, globalListener.m_numEventsX); // If environments are properly separated we should get only the events the global/default Environment!
  2815. }
  2816. // Test disconnecting while in ConnectionPolicy
  2817. class BusWithConnectionPolicy
  2818. : public AZ::EBusTraits
  2819. {
  2820. public:
  2821. virtual ~BusWithConnectionPolicy() = default;
  2822. virtual void MessageWhichOccursDuringConnect() = 0;
  2823. template<class Bus>
  2824. struct ConnectionPolicy : public AZ::EBusConnectionPolicy<Bus>
  2825. {
  2826. static void Connect(typename Bus::BusPtr&, typename Bus::Context&, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard& , const typename Bus::BusIdType&)
  2827. {
  2828. handler->MessageWhichOccursDuringConnect();
  2829. }
  2830. };
  2831. };
  2832. using BusWithConnectionPolicyBus = AZ::EBus<BusWithConnectionPolicy>;
  2833. class HandlerWhichDisconnectsDuringDelivery
  2834. : public BusWithConnectionPolicyBus::Handler
  2835. {
  2836. void MessageWhichOccursDuringConnect() override
  2837. {
  2838. BusDisconnect();
  2839. }
  2840. };
  2841. TEST_F(EBus, ConnectionPolicy_DisconnectDuringDelivery)
  2842. {
  2843. HandlerWhichDisconnectsDuringDelivery handlerTest;
  2844. handlerTest.BusConnect();
  2845. }
  2846. class BusWithConnectionPolicyUnlocksBeforeHandler
  2847. : public AZ::EBusTraits
  2848. {
  2849. public:
  2850. using MutexType = AZStd::recursive_mutex;
  2851. virtual ~BusWithConnectionPolicyUnlocksBeforeHandler() = default;
  2852. virtual int GetPreUnlockDelay() const { return 0; }
  2853. virtual int GetPostUnlockDelay() const { return 0; }
  2854. virtual bool ShouldUnlock() const { return true; }
  2855. virtual void MessageWhichOccursDuringConnect() = 0;
  2856. template<class Bus>
  2857. struct ConnectionPolicy : public AZ::EBusConnectionPolicy<Bus>
  2858. {
  2859. static void Connect(typename Bus::BusPtr&, typename Bus::Context&, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard& connectLock, const typename Bus::BusIdType&)
  2860. {
  2861. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(handler->GetPreUnlockDelay()));
  2862. if (handler->ShouldUnlock())
  2863. {
  2864. connectLock.unlock();
  2865. }
  2866. AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(handler->GetPostUnlockDelay()));
  2867. handler->MessageWhichOccursDuringConnect();
  2868. }
  2869. };
  2870. };
  2871. using BusWithConnectionPolicyUnlocksBus = AZ::EBus<BusWithConnectionPolicyUnlocksBeforeHandler>;
  2872. class DelayUnlockHandler
  2873. : public BusWithConnectionPolicyUnlocksBus::Handler
  2874. {
  2875. public:
  2876. DelayUnlockHandler() = default;
  2877. DelayUnlockHandler(int preDelay, int postDelay) :
  2878. m_preDelay(preDelay),
  2879. m_postDelay(postDelay)
  2880. {
  2881. }
  2882. void MessageWhichOccursDuringConnect() override
  2883. {
  2884. if (m_connectMethod)
  2885. {
  2886. m_connectMethod();
  2887. }
  2888. m_didConnect = true;
  2889. }
  2890. int GetPreUnlockDelay() const override { return m_preDelay; }
  2891. int GetPostUnlockDelay() const override { return m_postDelay; }
  2892. bool ShouldUnlock() const override { return m_shouldUnlock; }
  2893. bool m_shouldUnlock{ true };
  2894. AZStd::atomic_bool m_didConnect{ false };
  2895. int m_preDelay{ 0 };
  2896. int m_postDelay{ 0 };
  2897. AZStd::function<void()> m_connectMethod;
  2898. };
  2899. TEST_F(EBus, ConnectionPolicy_DisconnectDuringDeliveryUnlocked_Success)
  2900. {
  2901. DelayUnlockHandler handlerTest;
  2902. handlerTest.m_connectMethod = [&handlerTest]() { handlerTest.BusDisconnect(); };
  2903. handlerTest.BusConnect();
  2904. EXPECT_EQ(handlerTest.m_didConnect, true);
  2905. }
  2906. TEST_F(EBus, ConnectionPolicy_DisconnectDuringDeliveryDelayUnlocked_Success)
  2907. {
  2908. constexpr int numTests = 100;
  2909. for (int disconnectTest = 0; disconnectTest < numTests; ++disconnectTest)
  2910. {
  2911. DelayUnlockHandler handlerTest(0, 1);
  2912. handlerTest.BusConnect();
  2913. AZStd::thread disconnectThread([&handlerTest]()
  2914. {
  2915. handlerTest.BusDisconnect();
  2916. }
  2917. );
  2918. disconnectThread.join();
  2919. EXPECT_EQ(handlerTest.m_didConnect, true);
  2920. }
  2921. }
  2922. TEST_F(EBus, ConnectionPolicy_DisconnectDuringDeliveryPreDelayUnlocked_Success)
  2923. {
  2924. constexpr int numTests = 100;
  2925. for (int disconnectTest = 0; disconnectTest < numTests; ++disconnectTest)
  2926. {
  2927. DelayUnlockHandler handlerTest(1, 0);
  2928. handlerTest.BusConnect();
  2929. AZStd::thread disconnectThread([&handlerTest]()
  2930. {
  2931. handlerTest.BusDisconnect();
  2932. }
  2933. );
  2934. disconnectThread.join();
  2935. EXPECT_EQ(handlerTest.m_didConnect, true);
  2936. }
  2937. }
  2938. TEST_F(EBus, ConnectionPolicy_WaitOnSecondHandlerWhileStillLocked_CantComplete)
  2939. {
  2940. DelayUnlockHandler waitHandler;
  2941. // Test without releasing the lock - this is expected to prevent our second handler from connecting
  2942. // so will block this thread
  2943. waitHandler.m_shouldUnlock = false;
  2944. DelayUnlockHandler connectHandler;
  2945. waitHandler.m_connectMethod = [&connectHandler]()
  2946. {
  2947. constexpr int waitMsMax = 100;
  2948. auto startTime = AZStd::chrono::steady_clock::now();
  2949. auto endTime = startTime + AZStd::chrono::milliseconds(waitMsMax);
  2950. // The other bus should not be able to complete because we're still holding the connect lock
  2951. while (AZStd::chrono::steady_clock::now() < endTime && !connectHandler.BusIsConnected())
  2952. {
  2953. AZStd::this_thread::yield();
  2954. }
  2955. EXPECT_GE(AZStd::chrono::steady_clock::now(), endTime);
  2956. };
  2957. AZStd::thread connectThread([&connectHandler, &waitHandler]()
  2958. {
  2959. constexpr int waitMsMax = 100;
  2960. auto startTime = AZStd::chrono::steady_clock::now();
  2961. auto endTime = startTime + AZStd::chrono::milliseconds(waitMsMax);
  2962. while (AZStd::chrono::steady_clock::now() < endTime && !waitHandler.m_didConnect)
  2963. {
  2964. AZStd::this_thread::yield();
  2965. }
  2966. connectHandler.BusConnect();
  2967. }
  2968. );
  2969. waitHandler.BusConnect();
  2970. connectThread.join();
  2971. EXPECT_EQ(connectHandler.m_didConnect, true);
  2972. EXPECT_EQ(waitHandler.m_didConnect, true);
  2973. waitHandler.BusDisconnect();
  2974. connectHandler.BusDisconnect();
  2975. }
  2976. TEST_F(EBus, ConnectionPolicy_WaitOnSecondHandlerWhileUnlocked_CanComplete)
  2977. {
  2978. constexpr int numTests = 20;
  2979. for (int connectTest = 0; connectTest < numTests; ++connectTest)
  2980. {
  2981. DelayUnlockHandler waitHandler;
  2982. DelayUnlockHandler connectHandler;
  2983. waitHandler.m_connectMethod = [&connectHandler]()
  2984. {
  2985. // Check that a connection for the connectHandler has occured
  2986. // within a 1 second, which should be more than enough
  2987. // time for a connection to occur even when the system is under load
  2988. constexpr int waitMsMax = 1000;
  2989. auto startTime = AZStd::chrono::steady_clock::now();
  2990. auto endTime = startTime + AZStd::chrono::milliseconds(waitMsMax);
  2991. // The other bus should be able to connect
  2992. while (AZStd::chrono::steady_clock::now() < endTime && !connectHandler.m_didConnect)
  2993. {
  2994. AZStd::this_thread::yield();
  2995. }
  2996. EXPECT_EQ(connectHandler.BusIsConnected(), true);
  2997. EXPECT_LE(AZStd::chrono::steady_clock::now(), endTime);
  2998. };
  2999. AZStd::thread connectThread([&connectHandler]()
  3000. {
  3001. connectHandler.BusConnect();
  3002. });
  3003. waitHandler.BusConnect();
  3004. connectThread.join();
  3005. EXPECT_EQ(connectHandler.m_didConnect, true);
  3006. EXPECT_EQ(waitHandler.m_didConnect, true);
  3007. waitHandler.BusDisconnect();
  3008. connectHandler.BusDisconnect();
  3009. }
  3010. }
  3011. class IdBusWithConnectionPolicy
  3012. : public AZ::EBusTraits
  3013. {
  3014. public:
  3015. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  3016. using BusIdType = int64_t;
  3017. virtual ~IdBusWithConnectionPolicy() = default;
  3018. virtual void MessageWhichOccursDuringConnect() = 0;
  3019. virtual void MessageWhichOccursDuringDisconnect() = 0;
  3020. template<class Bus>
  3021. struct ConnectionPolicy : public AZ::EBusConnectionPolicy<Bus>
  3022. {
  3023. static void Connect(typename Bus::BusPtr&, typename Bus::Context&, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard& , const typename Bus::BusIdType&)
  3024. {
  3025. handler->MessageWhichOccursDuringConnect();
  3026. }
  3027. static void Disconnect([[maybe_unused]] typename Bus::Context& context, typename Bus::HandlerNode& handler, [[maybe_unused]] typename Bus::BusPtr& ptr)
  3028. {
  3029. handler->MessageWhichOccursDuringDisconnect();
  3030. }
  3031. };
  3032. };
  3033. using IdBusWithConnectionPolicyBus = AZ::EBus<IdBusWithConnectionPolicy>;
  3034. class MultiHandlerWhichDisconnectsDuringDelivery
  3035. : public IdBusWithConnectionPolicyBus::MultiHandler
  3036. {
  3037. void MessageWhichOccursDuringConnect() override
  3038. {
  3039. auto busIdRef = IdBusWithConnectionPolicyBus::GetCurrentBusId();
  3040. EXPECT_NE(nullptr, busIdRef);
  3041. BusDisconnect(*busIdRef);
  3042. }
  3043. void MessageWhichOccursDuringDisconnect() override
  3044. {
  3045. auto busIdRef = IdBusWithConnectionPolicyBus::GetCurrentBusId();
  3046. EXPECT_NE(nullptr, busIdRef);
  3047. }
  3048. };
  3049. static constexpr int64_t multiHandlerTestBusId = 42;
  3050. TEST_F(EBus, MultiHandlerConnectionPolicy_DisconnectDuringDelivery)
  3051. {
  3052. MultiHandlerWhichDisconnectsDuringDelivery multiHandlerTest;
  3053. multiHandlerTest.BusConnect(multiHandlerTestBusId);
  3054. EXPECT_EQ(0U, IdBusWithConnectionPolicyBus::GetTotalNumOfEventHandlers());
  3055. }
  3056. class BusWithConnectionAndDisconnectPolicy
  3057. : public AZ::EBusTraits
  3058. {
  3059. public:
  3060. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  3061. using BusIdType = int32_t;
  3062. virtual ~BusWithConnectionAndDisconnectPolicy() = default;
  3063. virtual void MessageWhichOccursDuringConnect(int32_t id) = 0;
  3064. virtual void MessageWhichOccursDuringDisconnect(int32_t id) = 0;
  3065. template<class Bus>
  3066. struct ConnectionPolicy : public AZ::EBusConnectionPolicy<Bus>
  3067. {
  3068. static void Connect(typename Bus::BusPtr& ptr, [[maybe_unused]] typename Bus::Context& context, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard&, const typename Bus::BusIdType& id)
  3069. {
  3070. EXPECT_EQ(handler.GetBusId(), id);
  3071. EXPECT_EQ(handler.m_holder, ptr);
  3072. handler->MessageWhichOccursDuringConnect(handler.GetBusId());
  3073. }
  3074. static void Disconnect([[maybe_unused]] typename Bus::Context& context, typename Bus::HandlerNode& handler, typename Bus::BusPtr& ptr)
  3075. {
  3076. EXPECT_EQ(handler.m_holder, ptr);
  3077. handler->MessageWhichOccursDuringDisconnect(handler.GetBusId());
  3078. }
  3079. };
  3080. };
  3081. using BusWithConnectionAndDisconnectPolicyBus = AZ::EBus<BusWithConnectionAndDisconnectPolicy>;
  3082. struct HandlerTrackingConnectionDisconnectionIds
  3083. : public BusWithConnectionAndDisconnectPolicyBus::Handler
  3084. {
  3085. void MessageWhichOccursDuringConnect(int32_t id) override
  3086. {
  3087. m_lastConnectId = id;
  3088. }
  3089. void MessageWhichOccursDuringDisconnect(int32_t id) override
  3090. {
  3091. m_lastDisconnectId = id;
  3092. }
  3093. int32_t m_lastConnectId = 0;
  3094. int32_t m_lastDisconnectId = 0;
  3095. };
  3096. TEST_F(EBus, ConnectionPolicy_ConnectDisconnect_CorrectIds)
  3097. {
  3098. HandlerTrackingConnectionDisconnectionIds idsHandler;
  3099. EXPECT_EQ(idsHandler.m_lastConnectId, 0);
  3100. EXPECT_EQ(idsHandler.m_lastDisconnectId, 0);
  3101. idsHandler.BusConnect(123);
  3102. EXPECT_TRUE(idsHandler.BusIsConnectedId(123));
  3103. EXPECT_EQ(idsHandler.m_lastConnectId, 123);
  3104. idsHandler.BusDisconnect(123);
  3105. EXPECT_FALSE(idsHandler.BusIsConnectedId(123));
  3106. EXPECT_EQ(idsHandler.m_lastDisconnectId, 123);
  3107. idsHandler.BusConnect(234);
  3108. EXPECT_TRUE(idsHandler.BusIsConnectedId(234));
  3109. EXPECT_EQ(idsHandler.m_lastConnectId, 234);
  3110. idsHandler.BusDisconnect();
  3111. EXPECT_FALSE(idsHandler.BusIsConnectedId(234));
  3112. EXPECT_EQ(idsHandler.m_lastDisconnectId, 234);
  3113. }
  3114. struct LastHandlerDisconnectInterface
  3115. : public AZ::EBusTraits
  3116. {
  3117. static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple;
  3118. static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::ById;
  3119. typedef size_t BusIdType;
  3120. virtual void OnEvent() = 0;
  3121. };
  3122. using LastHandlerDisconnectBus = AZ::EBus<LastHandlerDisconnectInterface>;
  3123. struct LastHandlerDisconnectHandler
  3124. : public LastHandlerDisconnectBus::Handler
  3125. {
  3126. void OnEvent() override
  3127. {
  3128. ++m_numOnEvents;
  3129. BusDisconnect();
  3130. }
  3131. unsigned int m_numOnEvents = 0;
  3132. };
  3133. TEST_F(EBus, LastHandlerDisconnectForward)
  3134. {
  3135. LastHandlerDisconnectHandler lastHandler;
  3136. lastHandler.BusConnect(0);
  3137. EBUS_EVENT_ID(0, LastHandlerDisconnectBus, OnEvent);
  3138. EXPECT_FALSE(lastHandler.BusIsConnected());
  3139. EXPECT_EQ(1, lastHandler.m_numOnEvents);
  3140. }
  3141. TEST_F(EBus, LastHandlerDisconnectReverse)
  3142. {
  3143. LastHandlerDisconnectHandler lastHandler;
  3144. lastHandler.BusConnect(0);
  3145. EBUS_EVENT_ID_REVERSE(0, LastHandlerDisconnectBus, OnEvent);
  3146. EXPECT_FALSE(lastHandler.BusIsConnected());
  3147. EXPECT_EQ(1, lastHandler.m_numOnEvents);
  3148. }
  3149. struct DisconnectAssertInterface
  3150. : public AZ::EBusTraits
  3151. {
  3152. using MutexType = AZStd::recursive_mutex;
  3153. virtual ~DisconnectAssertInterface() = default;
  3154. virtual void OnEvent() {};
  3155. };
  3156. using DisconnectAssertBus = AZ::EBus<DisconnectAssertInterface>;
  3157. struct DisconnectAssertHandler
  3158. : public DisconnectAssertBus::Handler
  3159. {
  3160. };
  3161. TEST_F(EBus, HandlerDestroyedWithoutDisconnect_Asserts)
  3162. {
  3163. // EBus handlers with a non-NullMutex assert on disconnect if they have not been explicitly disconnected before the internal EBus::Handler destructor is invoked.
  3164. // The reason for the assert is because the BusDisconnect call will lock the EBus context mutex to safely disconnect the handler, but if the handler is still
  3165. // connected to the EBus, another thread could access it after the vtable for the derived class has been reset.
  3166. AZ_TEST_START_TRACE_SUPPRESSION;
  3167. {
  3168. DisconnectAssertHandler handler;
  3169. handler.BusConnect();
  3170. }
  3171. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  3172. }
  3173. TEST_F(EBus, HandlerDestroyedAfterDisconnect_DoesNotAssert)
  3174. {
  3175. {
  3176. DisconnectAssertHandler handler;
  3177. handler.BusConnect();
  3178. handler.BusDisconnect();
  3179. }
  3180. }
  3181. struct SingleHandlerPerIdTestRequests
  3182. : public AZ::EBusTraits
  3183. {
  3184. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  3185. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  3186. using BusIdType = int32_t;
  3187. };
  3188. using SingleHandlerPerIdTestRequestBus = AZ::EBus<SingleHandlerPerIdTestRequests>;
  3189. struct SingleHandlerPerIdTestImpl : public SingleHandlerPerIdTestRequestBus::Handler
  3190. {
  3191. void Connect(SingleHandlerPerIdTestRequestBus::BusIdType busId)
  3192. {
  3193. SingleHandlerPerIdTestRequestBus::Handler::BusConnect(busId);
  3194. }
  3195. void Disconnect()
  3196. {
  3197. SingleHandlerPerIdTestRequestBus::Handler::BusDisconnect();
  3198. }
  3199. };
  3200. struct MultipleHandlersPerIdTestRequests
  3201. : public AZ::EBusTraits
  3202. {
  3203. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  3204. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
  3205. using BusIdType = int32_t;
  3206. };
  3207. using MultipleHandlersPerIdTestRequestBus = AZ::EBus<MultipleHandlersPerIdTestRequests>;
  3208. struct MultipleHandlersPerIdTestImpl
  3209. : public MultipleHandlersPerIdTestRequestBus::MultiHandler
  3210. {
  3211. void Connect(MultipleHandlersPerIdTestRequestBus::BusIdType busId)
  3212. {
  3213. MultipleHandlersPerIdTestRequestBus::MultiHandler::BusConnect(busId);
  3214. }
  3215. void Disconnect()
  3216. {
  3217. MultipleHandlersPerIdTestRequestBus::MultiHandler::BusDisconnect();
  3218. }
  3219. };
  3220. TEST_F(EBus, HasHandlersAddressId)
  3221. {
  3222. SingleHandlerPerIdTestImpl idTestRequest;
  3223. idTestRequest.Connect(4);
  3224. // note: arbitrary numbers selected
  3225. EXPECT_TRUE(SingleHandlerPerIdTestRequestBus::HasHandlers(4));
  3226. EXPECT_FALSE(SingleHandlerPerIdTestRequestBus::HasHandlers(10));
  3227. idTestRequest.Disconnect();
  3228. }
  3229. TEST_F(EBus, HasHandlersWithSingleHandlerListeningToMultipleIds)
  3230. {
  3231. MultipleHandlersPerIdTestImpl idTestRequest;
  3232. idTestRequest.Connect(4);
  3233. idTestRequest.Connect(7);
  3234. idTestRequest.Connect(10);
  3235. // note: arbitrary numbers selected
  3236. EXPECT_TRUE(MultipleHandlersPerIdTestRequestBus::HasHandlers(4));
  3237. EXPECT_TRUE(MultipleHandlersPerIdTestRequestBus::HasHandlers(7));
  3238. EXPECT_TRUE(MultipleHandlersPerIdTestRequestBus::HasHandlers(10));
  3239. EXPECT_FALSE(MultipleHandlersPerIdTestRequestBus::HasHandlers(15));
  3240. idTestRequest.Disconnect();
  3241. }
  3242. TEST_F(EBus, HasHandlersWithMultipleHandlersOnSameId)
  3243. {
  3244. MultipleHandlersPerIdTestImpl id1, id2;
  3245. id1.Connect(4);
  3246. id2.Connect(4);
  3247. EXPECT_TRUE(MultipleHandlersPerIdTestRequestBus::HasHandlers(4));
  3248. EXPECT_FALSE(MultipleHandlersPerIdTestRequestBus::HasHandlers(7));
  3249. }
  3250. TEST_F(EBus, HasHandlersWithTwoSingleHandlersOnDifferentIds)
  3251. {
  3252. SingleHandlerPerIdTestImpl id1, id2;
  3253. id1.Connect(4);
  3254. id2.Connect(5);
  3255. EXPECT_TRUE(SingleHandlerPerIdTestRequestBus::HasHandlers(4));
  3256. EXPECT_TRUE(SingleHandlerPerIdTestRequestBus::HasHandlers(5));
  3257. EXPECT_FALSE(SingleHandlerPerIdTestRequestBus::HasHandlers(7));
  3258. }
  3259. TEST_F(EBus, HasHandlersAddressPtr)
  3260. {
  3261. // note: arbitrary numbers selected
  3262. constexpr SingleHandlerPerIdTestRequestBus::BusIdType validBusId = 4;
  3263. constexpr SingleHandlerPerIdTestRequestBus::BusIdType invalidBusId = 10;
  3264. SingleHandlerPerIdTestImpl idTestRequest;
  3265. idTestRequest.Connect(validBusId);
  3266. SingleHandlerPerIdTestRequestBus::BusPtr validBusIdPtr;
  3267. SingleHandlerPerIdTestRequestBus::Bind(validBusIdPtr, validBusId);
  3268. SingleHandlerPerIdTestRequestBus::BusPtr invalidBusIdPtr;
  3269. SingleHandlerPerIdTestRequestBus::Bind(invalidBusIdPtr, invalidBusId);
  3270. EXPECT_TRUE(SingleHandlerPerIdTestRequestBus::HasHandlers(validBusIdPtr));
  3271. EXPECT_FALSE(SingleHandlerPerIdTestRequestBus::HasHandlers(invalidBusIdPtr));
  3272. idTestRequest.Disconnect();
  3273. }
  3274. // IsInDispatchThisThread
  3275. struct IsInThreadDispatchRequests
  3276. : AZ::EBusTraits
  3277. {
  3278. using MutexType = AZStd::recursive_mutex;
  3279. };
  3280. using IsInThreadDispatchBus = AZ::EBus<IsInThreadDispatchRequests>;
  3281. class IsInThreadDispatchHandler
  3282. : public IsInThreadDispatchBus::Handler
  3283. {};
  3284. TEST_F(EBus, InvokingIsInThisThread_ReturnsSuccess_OnlyIfThreadIsInDispatch)
  3285. {
  3286. IsInThreadDispatchHandler handler;
  3287. handler.BusConnect();
  3288. auto ThreadDispatcher = [](IsInThreadDispatchRequests*)
  3289. {
  3290. EXPECT_TRUE(IsInThreadDispatchBus::IsInDispatchThisThread());
  3291. auto PerThreadBusDispatch = []()
  3292. {
  3293. EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
  3294. };
  3295. AZStd::array threads{ AZStd::thread(PerThreadBusDispatch), AZStd::thread(PerThreadBusDispatch) };
  3296. for (AZStd::thread& thread : threads)
  3297. {
  3298. thread.join();
  3299. }
  3300. };
  3301. static constexpr size_t ThreadDispatcherIterations = 4;
  3302. for (size_t iteration = 0; iteration < ThreadDispatcherIterations; ++iteration)
  3303. {
  3304. EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
  3305. IsInThreadDispatchBus::Broadcast(ThreadDispatcher);
  3306. EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
  3307. }
  3308. }
  3309. // Thread Dispatch Policy
  3310. struct ThreadDispatchTestBusTraits
  3311. : AZ::EBusTraits
  3312. {
  3313. using MutexType = AZStd::recursive_mutex;
  3314. struct PostThreadDispatchTestInvoker
  3315. {
  3316. ~PostThreadDispatchTestInvoker();
  3317. };
  3318. template <typename DispatchMutex>
  3319. struct ThreadDispatchTestLockGuard
  3320. {
  3321. ThreadDispatchTestLockGuard(DispatchMutex& contextMutex)
  3322. : m_lock{ contextMutex }
  3323. {}
  3324. ThreadDispatchTestLockGuard(DispatchMutex& contextMutex, AZStd::adopt_lock_t adopt_lock)
  3325. : m_lock{ contextMutex, adopt_lock }
  3326. {}
  3327. ThreadDispatchTestLockGuard(const ThreadDispatchTestLockGuard&) = delete;
  3328. ThreadDispatchTestLockGuard& operator=(const ThreadDispatchTestLockGuard&) = delete;
  3329. private:
  3330. PostThreadDispatchTestInvoker m_threadPolicyInvoker;
  3331. using LockType = AZStd::conditional_t<LocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
  3332. LockType m_lock;
  3333. };
  3334. template <typename DispatchMutex, bool IsLocklessDispatch>
  3335. using DispatchLockGuard = ThreadDispatchTestLockGuard<DispatchMutex>;
  3336. static inline AZStd::atomic<int32_t> s_threadPostDispatchCalls;
  3337. };
  3338. class ThreadDispatchTestRequests
  3339. {
  3340. public:
  3341. virtual void FirstCall() = 0;
  3342. virtual void SecondCall() = 0;
  3343. virtual void ThirdCall() = 0;
  3344. };
  3345. using ThreadDispatchTestBus = AZ::EBus<ThreadDispatchTestRequests, ThreadDispatchTestBusTraits>;
  3346. ThreadDispatchTestBusTraits::PostThreadDispatchTestInvoker::~PostThreadDispatchTestInvoker()
  3347. {
  3348. if (!ThreadDispatchTestBus::IsInDispatchThisThread())
  3349. {
  3350. ++s_threadPostDispatchCalls;
  3351. }
  3352. }
  3353. class ThreadDispatchTestHandler
  3354. : public ThreadDispatchTestBus::Handler
  3355. {
  3356. public:
  3357. void Connect()
  3358. {
  3359. ThreadDispatchTestBus::Handler::BusConnect();
  3360. }
  3361. void Disconnect()
  3362. {
  3363. ThreadDispatchTestBus::Handler::BusDisconnect();
  3364. }
  3365. void FirstCall() override
  3366. {
  3367. ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall);
  3368. }
  3369. void SecondCall() override
  3370. {
  3371. ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall);
  3372. }
  3373. void ThirdCall() override
  3374. {
  3375. }
  3376. };
  3377. template <typename ParamType>
  3378. class EBusParamFixture
  3379. : public LeakDetectionFixture
  3380. , public ::testing::WithParamInterface<ParamType>
  3381. {};
  3382. struct ThreadDispatchParams
  3383. {
  3384. size_t m_threadCount{};
  3385. size_t m_handlerCount{};
  3386. };
  3387. using ThreadDispatchParamFixture = EBusParamFixture<ThreadDispatchParams>;
  3388. INSTANTIATE_TEST_SUITE_P(
  3389. ThreadDispatch,
  3390. ThreadDispatchParamFixture,
  3391. ::testing::Values(
  3392. ThreadDispatchParams{ 1, 1 },
  3393. ThreadDispatchParams{ 2, 1 },
  3394. ThreadDispatchParams{ 1, 2 },
  3395. ThreadDispatchParams{ 2, 2 },
  3396. ThreadDispatchParams{ 16, 8 }
  3397. )
  3398. );
  3399. TEST_P(ThreadDispatchParamFixture, CustomDispatchLockGuard_InvokesPostDispatchFunction_AfterThreadHasFinishedDispatch)
  3400. {
  3401. ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0;
  3402. ThreadDispatchParams threadDispatchParams = GetParam();
  3403. AZStd::vector<AZStd::thread> testThreads;
  3404. AZStd::vector<ThreadDispatchTestHandler> testHandlers(threadDispatchParams.m_handlerCount);
  3405. for (ThreadDispatchTestHandler& testHandler : testHandlers)
  3406. {
  3407. testHandler.Connect();
  3408. }
  3409. static constexpr size_t DispatchThreadCalls = 3;
  3410. const size_t totalThreadDispatchCalls = threadDispatchParams.m_threadCount * DispatchThreadCalls;
  3411. auto DispatchThreadWorker = []()
  3412. {
  3413. ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::FirstCall);
  3414. ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall);
  3415. ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall);
  3416. };
  3417. for (size_t threadIndex = 0; threadIndex < threadDispatchParams.m_threadCount; ++threadIndex)
  3418. {
  3419. testThreads.emplace_back(DispatchThreadWorker);
  3420. }
  3421. for (AZStd::thread& thread : testThreads)
  3422. {
  3423. thread.join();
  3424. }
  3425. for (ThreadDispatchTestHandler& testHandler : testHandlers)
  3426. {
  3427. testHandler.Disconnect();
  3428. }
  3429. EXPECT_EQ(totalThreadDispatchCalls, ThreadDispatchTestBusTraits::s_threadPostDispatchCalls);
  3430. ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0;
  3431. }
  3432. struct ReentrantEBusUseTestRequests : public AZ::EBusTraits
  3433. {
  3434. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
  3435. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  3436. using BusIdType = int32_t;
  3437. // This event will directly call itself recursively via EBus.
  3438. virtual void EventDirectlyCallsItself(bool expectedReentrantResult) = 0;
  3439. // The first event will call the second event via EBus.
  3440. virtual void EventCallsOtherEventOnSameEBus() = 0;
  3441. virtual bool EventCalledByOtherEventOnSameEBus() = 0;
  3442. // The first event will call the second event via EBus, but on different bus IDs.
  3443. virtual void EventCallsOtherEventOnDifferentEBusId(BusIdType busId) = 0;
  3444. virtual bool EventCalledByOtherEventOnDifferentEBusId() = 0;
  3445. };
  3446. using ReentrantEBusUseTestRequestBus = AZ::EBus<ReentrantEBusUseTestRequests>;
  3447. struct ReentrantEBusUseTestImpl : public ReentrantEBusUseTestRequestBus::Handler
  3448. {
  3449. ReentrantEBusUseTestImpl(ReentrantEBusUseTestRequestBus::BusIdType busId)
  3450. {
  3451. m_busId = busId;
  3452. ReentrantEBusUseTestRequestBus::Handler::BusConnect(busId);
  3453. }
  3454. ~ReentrantEBusUseTestImpl()
  3455. {
  3456. ReentrantEBusUseTestRequestBus::Handler::BusDisconnect();
  3457. }
  3458. void EventDirectlyCallsItself(bool expectedReentrantResult) override
  3459. {
  3460. // Verify that we get the expected API result. (We use ASSERT_EQ because a test failure here might cause infinite recursion)
  3461. ASSERT_EQ(ReentrantEBusUseTestRequestBus::HasReentrantEBusUseThisThread(), expectedReentrantResult);
  3462. // Avoid infinite recursion. :)
  3463. if (ReentrantEBusUseTestRequestBus::HasReentrantEBusUseThisThread())
  3464. {
  3465. return;
  3466. }
  3467. // This event calls itself via a nested EBus call. We expect the nested call to detect the reentrancy.
  3468. ReentrantEBusUseTestRequestBus::Event(m_busId, &ReentrantEBusUseTestRequestBus::Events::EventDirectlyCallsItself, true);
  3469. }
  3470. void EventCallsOtherEventOnSameEBus() override
  3471. {
  3472. // Call a second event on the same EBus and verify that it was called.
  3473. bool otherEventCalled = false;
  3474. ReentrantEBusUseTestRequestBus::EventResult(otherEventCalled, m_busId,
  3475. &ReentrantEBusUseTestRequestBus::Events::EventCalledByOtherEventOnSameEBus);
  3476. EXPECT_TRUE(otherEventCalled);
  3477. }
  3478. bool EventCalledByOtherEventOnSameEBus() override
  3479. {
  3480. // Verify that even though two different events have been called on the same EBus,
  3481. // it is still considered reentrant use of the ebus itself.
  3482. EXPECT_TRUE(ReentrantEBusUseTestRequestBus::HasReentrantEBusUseThisThread());
  3483. return true;
  3484. }
  3485. void EventCallsOtherEventOnDifferentEBusId(BusIdType busId) override
  3486. {
  3487. // Call a second event on a different EBus and verify that it was called.
  3488. bool otherEventCalled = false;
  3489. ReentrantEBusUseTestRequestBus::EventResult(otherEventCalled, busId,
  3490. &ReentrantEBusUseTestRequestBus::Events::EventCalledByOtherEventOnDifferentEBusId);
  3491. EXPECT_TRUE(otherEventCalled);
  3492. }
  3493. bool EventCalledByOtherEventOnDifferentEBusId() override
  3494. {
  3495. // Verify that two different nested events on the same EBus but with different EBus IDs will not be detected as reentrant.
  3496. EXPECT_FALSE(ReentrantEBusUseTestRequestBus::HasReentrantEBusUseThisThread());
  3497. return true;
  3498. }
  3499. protected:
  3500. ReentrantEBusUseTestRequestBus::BusIdType m_busId;
  3501. };
  3502. TEST_F(EBus, ReentrantEBusUsageDetectedFromNestedDirectCalls)
  3503. {
  3504. constexpr int32_t busId = 4;
  3505. ReentrantEBusUseTestImpl reentrantEBusUseTestRequest(busId);
  3506. constexpr bool expectedReentrantResult = false;
  3507. ReentrantEBusUseTestRequestBus::Event(
  3508. busId, &ReentrantEBusUseTestRequestBus::Events::EventDirectlyCallsItself, expectedReentrantResult);
  3509. }
  3510. TEST_F(EBus, ReentrantEBusUsageDetectedFromTwoSeparateCallsOnSameBus)
  3511. {
  3512. constexpr int32_t busId = 4;
  3513. ReentrantEBusUseTestImpl reentrantEBusUseTestRequest(busId);
  3514. ReentrantEBusUseTestRequestBus::Event(busId, &ReentrantEBusUseTestRequestBus::Events::EventCallsOtherEventOnSameEBus);
  3515. }
  3516. TEST_F(EBus, ReentrantEBusUsageNotDetectedFromTwoSeparateCallsOnSameBusWithDifferentIds)
  3517. {
  3518. constexpr int32_t busId = 4;
  3519. ReentrantEBusUseTestImpl reentrantEBusUseTestRequest(busId);
  3520. constexpr int32_t secondBusId = 8;
  3521. ReentrantEBusUseTestImpl secondReentrantEBusUseTestRequest(secondBusId);
  3522. ReentrantEBusUseTestRequestBus::Event(busId,
  3523. &ReentrantEBusUseTestRequestBus::Events::EventCallsOtherEventOnDifferentEBusId, secondBusId);
  3524. }
  3525. } // namespace UnitTest
  3526. #if defined(HAVE_BENCHMARK)
  3527. //-------------------------------------------------------------------------
  3528. // PERF TESTS
  3529. //-------------------------------------------------------------------------
  3530. namespace Benchmark
  3531. {
  3532. namespace BenchmarkSettings
  3533. {
  3534. namespace
  3535. {
  3536. // How many addresses/handlers count as "many"
  3537. static const int Many = 1000;
  3538. }
  3539. void Common(::benchmark::internal::Benchmark* benchmark)
  3540. {
  3541. benchmark
  3542. ->Unit(::benchmark::kNanosecond)
  3543. ;
  3544. }
  3545. void OneToOne(::benchmark::internal::Benchmark* benchmark)
  3546. {
  3547. Common(benchmark);
  3548. benchmark
  3549. ->ArgNames({ { "Addresses" },{ "Handlers" } })
  3550. ->Args({ 0, 0 })
  3551. ->Args({ 1, 1 })
  3552. ;
  3553. }
  3554. void OneToMany(::benchmark::internal::Benchmark* benchmark)
  3555. {
  3556. OneToOne(benchmark);
  3557. benchmark
  3558. ->Args({ 1, Many })
  3559. ;
  3560. }
  3561. void ManyToOne(::benchmark::internal::Benchmark* benchmark)
  3562. {
  3563. OneToOne(benchmark);
  3564. benchmark
  3565. ->Args({ Many, 1 })
  3566. ;
  3567. }
  3568. void ManyToMany(::benchmark::internal::Benchmark* benchmark)
  3569. {
  3570. OneToOne(benchmark);
  3571. benchmark
  3572. ->Args({ 1, Many })
  3573. ->Args({ Many, 1 })
  3574. ->Args({ Many, Many })
  3575. ;
  3576. }
  3577. // Expected that this will be called after one of the above, so Common not called
  3578. void Multithreaded(::benchmark::internal::Benchmark* benchmark)
  3579. {
  3580. benchmark
  3581. ->ThreadRange(1, 8)
  3582. ->ThreadPerCpu();
  3583. ;
  3584. }
  3585. }
  3586. // AZ Benchmark environment used to initialize all EBus Handlers and then shared them with each benchmark test
  3587. template<typename Bus>
  3588. class BM_EBusEnvironment
  3589. : public AZ::Test::BenchmarkEnvironmentBase
  3590. {
  3591. public:
  3592. using BusType = Bus;
  3593. using HandlerT = Handler<Bus>;
  3594. BM_EBusEnvironment()
  3595. {
  3596. }
  3597. void SetUpBenchmark() override
  3598. {
  3599. // Created the container for the EBusHandlers
  3600. m_handlers = std::make_unique<std::vector<HandlerT>>();
  3601. // Connect handlers
  3602. constexpr bool multiAddress = Bus::Traits::AddressPolicy != AZ::EBusAddressPolicy::Single;
  3603. constexpr bool multiHandler = Bus::Traits::HandlerPolicy != AZ::EBusHandlerPolicy::Single;
  3604. constexpr int64_t numAddresses{ multiAddress ? BenchmarkSettings::Many : 1 };
  3605. constexpr int64_t numHandlers{ multiHandler ? BenchmarkSettings::Many : 1 };
  3606. constexpr bool connectOnConstruct{ false };
  3607. AZ::BetterPseudoRandom random;
  3608. m_handlers->reserve(numAddresses * numHandlers);
  3609. for (int64_t address = 0; address < numAddresses; ++address)
  3610. {
  3611. for (int64_t handler = 0; handler < numHandlers; ++handler)
  3612. {
  3613. int handlerOrder{};
  3614. random.GetRandom(handlerOrder);
  3615. m_handlers->emplace_back(HandlerT(static_cast<int>(address), handlerOrder, connectOnConstruct));
  3616. }
  3617. }
  3618. }
  3619. void TearDownBenchmark() override
  3620. {
  3621. // Deallocate the memory associated with the EBusHandlers
  3622. m_handlers.reset();
  3623. }
  3624. void Connect(::benchmark::State& state)
  3625. {
  3626. int64_t numAddresses = state.range(0);
  3627. int64_t numHandlers = state.range(1);
  3628. const size_t totalHandlers = static_cast<size_t>(numAddresses * numHandlers);
  3629. // Connect handlers
  3630. for (size_t handlerIndex = 0; handlerIndex < totalHandlers; ++handlerIndex)
  3631. {
  3632. if(handlerIndex < m_handlers->size())
  3633. {
  3634. (*m_handlers)[handlerIndex].Connect();
  3635. }
  3636. }
  3637. }
  3638. void Disconnect(::benchmark::State& state)
  3639. {
  3640. int64_t numAddresses = state.range(0);
  3641. int64_t numHandlers = state.range(1);
  3642. const size_t totalHandlers = static_cast<size_t>(numAddresses * numHandlers);
  3643. // Disconnect handlers
  3644. for (size_t handlerIndex = 0; handlerIndex < totalHandlers; ++handlerIndex)
  3645. {
  3646. if (handlerIndex < m_handlers->size())
  3647. {
  3648. (*m_handlers)[handlerIndex].Disconnect();
  3649. }
  3650. }
  3651. }
  3652. protected:
  3653. std::unique_ptr<std::vector<HandlerT>> m_handlers;
  3654. };
  3655. // Using a variable template to initialize the benchmark EBus_Environment on template instantiation
  3656. template<typename Bus>
  3657. static BM_EBusEnvironment<Bus>& s_benchmarkEBusEnv = AZ::Test::RegisterBenchmarkEnvironment<BM_EBusEnvironment<Bus>>();
  3658. // Internal macro callback for listing all buses requiring ids
  3659. #define BUS_BENCHMARK_PRIVATE_LIST_ID(cb, fn) \
  3660. cb(fn, ManyToOne, ManyToOne) \
  3661. cb(fn, ManyToMany, ManyToMany) \
  3662. cb(fn, ManyToManyOrdered, ManyToMany) \
  3663. cb(fn, ManyOrderedToOne, ManyToOne) \
  3664. cb(fn, ManyOrderedToMany, ManyToMany) \
  3665. cb(fn, ManyOrderedToManyOrdered, ManyToMany)
  3666. // Internal macro callback for listing all buses
  3667. #define BUS_BENCHMARK_PRIVATE_LIST_ALL(cb, fn) \
  3668. cb(fn, OneToOne, OneToOne) \
  3669. cb(fn, OneToMany, OneToMany) \
  3670. cb(fn, OneToManyOrdered, OneToMany) \
  3671. BUS_BENCHMARK_PRIVATE_LIST_ID(cb, fn)
  3672. // Internal macro callback for registering a benchmark
  3673. #define BUS_BENCHMARK_PRIVATE_REGISTER(fn, BusDef, SettingsFn) BENCHMARK_TEMPLATE(fn, BusDef)->Apply(&BenchmarkSettings::SettingsFn);
  3674. // Register a benchmark for all bus permutations requiring ids
  3675. #define BUS_BENCHMARK_REGISTER_ID(fn) BUS_BENCHMARK_PRIVATE_LIST_ID(BUS_BENCHMARK_PRIVATE_REGISTER, fn)
  3676. // Register a benchmark for all bus permutations
  3677. #define BUS_BENCHMARK_REGISTER_ALL(fn) BUS_BENCHMARK_PRIVATE_LIST_ALL(BUS_BENCHMARK_PRIVATE_REGISTER, fn)
  3678. //////////////////////////////////////////////////////////////////////////
  3679. // Single Threaded Events/Broadcasts
  3680. //////////////////////////////////////////////////////////////////////////
  3681. // Baseline benchmark for raw vtable call
  3682. static void BM_EBus_RawCall(::benchmark::State& state)
  3683. {
  3684. constexpr bool connectOnConstruct{ true };
  3685. AZStd::unique_ptr<Handler<OneToOne>> handler = AZStd::make_unique<Handler<OneToOne>>(0, connectOnConstruct);
  3686. while (state.KeepRunning())
  3687. {
  3688. handler->OnEvent();
  3689. }
  3690. }
  3691. BENCHMARK(BM_EBus_RawCall)->Apply(&BenchmarkSettings::Common);
  3692. #define BUS_BENCHMARK_PRIVATE_REGISTER_CONNECTION(fn, BusDef, _) BENCHMARK_TEMPLATE(fn, BusDef)->Apply(&BenchmarkSettings::Common);
  3693. template <typename Bus>
  3694. static void BM_EBus_BusConnect(::benchmark::State& state)
  3695. {
  3696. constexpr bool connectOnConstruct{ false };
  3697. Handler<Bus> handler{ 0, connectOnConstruct };
  3698. while (state.KeepRunning())
  3699. {
  3700. handler.Connect();
  3701. // Pause timing, and disconnect
  3702. state.PauseTiming();
  3703. handler.BusDisconnect();
  3704. state.ResumeTiming();
  3705. }
  3706. }
  3707. BUS_BENCHMARK_PRIVATE_LIST_ALL(BUS_BENCHMARK_PRIVATE_REGISTER_CONNECTION, BM_EBus_BusConnect);
  3708. template <typename Bus>
  3709. static void BM_EBus_BusDisconnect(::benchmark::State& state)
  3710. {
  3711. constexpr bool connectOnConstruct{ true };
  3712. Handler<Bus> handler{ 0, connectOnConstruct };
  3713. while (state.KeepRunning())
  3714. {
  3715. handler.BusDisconnect();
  3716. // Pause timing, and reconnect
  3717. state.PauseTiming();
  3718. handler.Connect();
  3719. state.ResumeTiming();
  3720. }
  3721. }
  3722. BUS_BENCHMARK_PRIVATE_LIST_ALL(BUS_BENCHMARK_PRIVATE_REGISTER_CONNECTION, BM_EBus_BusDisconnect);
  3723. #undef BUS_BENCHMARK_PRIVATE_REGISTER_CONNECTION
  3724. template <typename Bus>
  3725. static void BM_EBus_EnumerateHandlers(::benchmark::State& state)
  3726. {
  3727. auto OnEventVisitor = [](typename Bus::InterfaceType* interfaceInst) -> bool
  3728. {
  3729. interfaceInst->OnEvent();
  3730. return true;
  3731. };
  3732. s_benchmarkEBusEnv<Bus>.Connect(state);
  3733. while (state.KeepRunning())
  3734. {
  3735. Bus::EnumerateHandlers(OnEventVisitor);
  3736. }
  3737. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3738. }
  3739. BUS_BENCHMARK_REGISTER_ALL(BM_EBus_EnumerateHandlers);
  3740. template <typename Bus>
  3741. static void BM_EBus_Broadcast(::benchmark::State& state)
  3742. {
  3743. s_benchmarkEBusEnv<Bus>.Connect(state);
  3744. while (state.KeepRunning())
  3745. {
  3746. Bus::Broadcast(&Bus::Events::OnEvent);
  3747. }
  3748. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3749. }
  3750. BUS_BENCHMARK_REGISTER_ALL(BM_EBus_Broadcast);
  3751. template <typename Bus>
  3752. static void BM_EBus_BroadcastResult(::benchmark::State& state)
  3753. {
  3754. s_benchmarkEBusEnv<Bus>.Connect(state);
  3755. while (state.KeepRunning())
  3756. {
  3757. int result = 0;
  3758. Bus::BroadcastResult(result, &Bus::Events::OnEvent);
  3759. ::benchmark::DoNotOptimize(result);
  3760. }
  3761. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3762. }
  3763. BUS_BENCHMARK_REGISTER_ALL(BM_EBus_BroadcastResult);
  3764. template <typename Bus>
  3765. static void BM_EBus_Event(::benchmark::State& state)
  3766. {
  3767. s_benchmarkEBusEnv<Bus>.Connect(state);
  3768. while (state.KeepRunning())
  3769. {
  3770. Bus::Event(1, &Bus::Events::OnEvent);
  3771. }
  3772. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3773. }
  3774. BUS_BENCHMARK_REGISTER_ID(BM_EBus_Event);
  3775. template <typename Bus>
  3776. static void BM_EBus_EventResult(::benchmark::State& state)
  3777. {
  3778. s_benchmarkEBusEnv<Bus>.Connect(state);
  3779. while (state.KeepRunning())
  3780. {
  3781. int result = 0;
  3782. Bus::EventResult(result, 1, &Bus::Events::OnEvent);
  3783. ::benchmark::DoNotOptimize(result);
  3784. }
  3785. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3786. }
  3787. BUS_BENCHMARK_REGISTER_ID(BM_EBus_EventResult);
  3788. template <typename Bus>
  3789. static void BM_EBus_EventCached(::benchmark::State& state)
  3790. {
  3791. s_benchmarkEBusEnv<Bus>.Connect(state);
  3792. typename Bus::BusPtr cachedPtr;
  3793. constexpr typename Bus::BusIdType firstConnectedAddressId{ 0 };
  3794. Bus::Bind(cachedPtr, firstConnectedAddressId);
  3795. while (state.KeepRunning())
  3796. {
  3797. Bus::Event(cachedPtr, &Bus::Events::OnEvent);
  3798. }
  3799. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3800. }
  3801. BUS_BENCHMARK_REGISTER_ID(BM_EBus_EventCached);
  3802. template <typename Bus>
  3803. static void BM_EBus_EventCachedResult(::benchmark::State& state)
  3804. {
  3805. s_benchmarkEBusEnv<Bus>.Connect(state);
  3806. typename Bus::BusPtr cachedPtr;
  3807. constexpr typename Bus::BusIdType firstConnectedAddressId{ 0 };
  3808. Bus::Bind(cachedPtr, firstConnectedAddressId);
  3809. while (state.KeepRunning())
  3810. {
  3811. int result = 0;
  3812. Bus::EventResult(result, cachedPtr, &Bus::Events::OnEvent);
  3813. ::benchmark::DoNotOptimize(result);
  3814. }
  3815. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3816. }
  3817. BUS_BENCHMARK_REGISTER_ID(BM_EBus_EventCachedResult);
  3818. //////////////////////////////////////////////////////////////////////////
  3819. // Broadcast/Event Queuing
  3820. //////////////////////////////////////////////////////////////////////////
  3821. // Broadcast
  3822. template <typename Bus>
  3823. static void BM_EBus_QueueBroadcast(::benchmark::State& state)
  3824. {
  3825. while (state.KeepRunning())
  3826. {
  3827. Bus::QueueBroadcast(&Bus::Events::OnEvent);
  3828. // Pause timing, and reset the queue
  3829. state.PauseTiming();
  3830. Bus::ClearQueuedEvents();
  3831. state.ResumeTiming();
  3832. }
  3833. }
  3834. BUS_BENCHMARK_REGISTER_ALL(BM_EBus_QueueBroadcast);
  3835. template <typename Bus>
  3836. static void BM_EBus_ExecuteBroadcast(::benchmark::State& state)
  3837. {
  3838. s_benchmarkEBusEnv<Bus>.Connect(state);
  3839. while (state.KeepRunning())
  3840. {
  3841. // Push an event to the queue to run
  3842. state.PauseTiming();
  3843. Bus::QueueBroadcast(&Bus::Events::OnEvent);
  3844. state.ResumeTiming();
  3845. Bus::ExecuteQueuedEvents();
  3846. }
  3847. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3848. }
  3849. BUS_BENCHMARK_REGISTER_ALL(BM_EBus_ExecuteBroadcast);
  3850. // Event
  3851. template <typename Bus>
  3852. static void BM_EBus_QueueEvent(::benchmark::State& state)
  3853. {
  3854. while (state.KeepRunning())
  3855. {
  3856. Bus::QueueEvent(1, &Bus::Events::OnEvent);
  3857. // Pause timing, and reset the queue
  3858. state.PauseTiming();
  3859. Bus::ClearQueuedEvents();
  3860. state.ResumeTiming();
  3861. }
  3862. }
  3863. BUS_BENCHMARK_REGISTER_ID(BM_EBus_QueueEvent);
  3864. template <typename Bus>
  3865. static void BM_EBus_ExecuteEvent(::benchmark::State& state)
  3866. {
  3867. s_benchmarkEBusEnv<Bus>.Connect(state);
  3868. while (state.KeepRunning())
  3869. {
  3870. // Push an event to the queue to run
  3871. state.PauseTiming();
  3872. Bus::QueueEvent(1, &Bus::Events::OnEvent);
  3873. state.ResumeTiming();
  3874. Bus::ExecuteQueuedEvents();
  3875. }
  3876. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3877. }
  3878. BUS_BENCHMARK_REGISTER_ID(BM_EBus_ExecuteEvent);
  3879. // Event Cached
  3880. template <typename Bus>
  3881. static void BM_EBus_QueueEventCached(::benchmark::State& state)
  3882. {
  3883. typename Bus::BusPtr cachedPtr;
  3884. constexpr typename Bus::BusIdType firstConnectedAddressId{ 0 };
  3885. Bus::Bind(cachedPtr, firstConnectedAddressId);
  3886. while (state.KeepRunning())
  3887. {
  3888. Bus::QueueEvent(cachedPtr, &Bus::Events::OnEvent);
  3889. // Pause timing, and reset the queue
  3890. state.PauseTiming();
  3891. Bus::ClearQueuedEvents();
  3892. state.ResumeTiming();
  3893. }
  3894. }
  3895. BUS_BENCHMARK_REGISTER_ID(BM_EBus_QueueEventCached);
  3896. template <typename Bus>
  3897. static void BM_EBus_ExecuteQueueCached(::benchmark::State& state)
  3898. {
  3899. s_benchmarkEBusEnv<Bus>.Connect(state);
  3900. typename Bus::BusPtr cachedPtr;
  3901. constexpr typename Bus::BusIdType firstConnectedAddressId{ 0 };
  3902. Bus::Bind(cachedPtr, firstConnectedAddressId);
  3903. while (state.KeepRunning())
  3904. {
  3905. // Push an event to the queue to run
  3906. state.PauseTiming();
  3907. Bus::QueueEvent(cachedPtr, &Bus::Events::OnEvent);
  3908. state.ResumeTiming();
  3909. Bus::ExecuteQueuedEvents();
  3910. }
  3911. s_benchmarkEBusEnv<Bus>.Disconnect(state);
  3912. }
  3913. BUS_BENCHMARK_REGISTER_ID(BM_EBus_ExecuteQueueCached);
  3914. //////////////////////////////////////////////////////////////////////////
  3915. // Multithreaded Broadcasts
  3916. //////////////////////////////////////////////////////////////////////////
  3917. static void BM_EBus_Multithreaded_Locks(::benchmark::State& state)
  3918. {
  3919. using Bus = TestBus<AZ::EBusAddressPolicy::Single, AZ::EBusHandlerPolicy::Multiple, false>;
  3920. AZStd::unique_ptr<BM_EBusEnvironment<Bus>> ebusBenchmarkEnv;
  3921. if (state.thread_index() == 0)
  3922. {
  3923. ebusBenchmarkEnv = AZStd::make_unique<BM_EBusEnvironment<Bus>>();
  3924. ebusBenchmarkEnv->SetUpBenchmark();
  3925. ebusBenchmarkEnv->Connect(state);
  3926. }
  3927. while (state.KeepRunning())
  3928. {
  3929. Bus::Broadcast(&Bus::Events::OnWait);
  3930. };
  3931. if (state.thread_index() == 0)
  3932. {
  3933. ebusBenchmarkEnv->Disconnect(state);
  3934. ebusBenchmarkEnv->TearDownBenchmark();
  3935. }
  3936. }
  3937. BENCHMARK(BM_EBus_Multithreaded_Locks)->Apply(&BenchmarkSettings::OneToMany)->Apply(&BenchmarkSettings::Multithreaded);
  3938. static void BM_EBus_Multithreaded_Lockless(::benchmark::State& state)
  3939. {
  3940. using Bus = TestBus<AZ::EBusAddressPolicy::Single, AZ::EBusHandlerPolicy::Multiple, true>;
  3941. AZStd::unique_ptr<BM_EBusEnvironment<Bus>> ebusBenchmarkEnv;
  3942. if (state.thread_index() == 0)
  3943. {
  3944. ebusBenchmarkEnv = AZStd::make_unique<BM_EBusEnvironment<Bus>>();
  3945. ebusBenchmarkEnv->SetUpBenchmark();
  3946. ebusBenchmarkEnv->Connect(state);
  3947. }
  3948. while (state.KeepRunning())
  3949. {
  3950. Bus::Broadcast(&Bus::Events::OnWait);
  3951. };
  3952. if (state.thread_index() == 0)
  3953. {
  3954. ebusBenchmarkEnv->Disconnect(state);
  3955. ebusBenchmarkEnv->TearDownBenchmark();
  3956. }
  3957. }
  3958. BENCHMARK(BM_EBus_Multithreaded_Lockless)->Apply(&BenchmarkSettings::OneToMany)->Apply(&BenchmarkSettings::Multithreaded);
  3959. }
  3960. #endif // HAVE_BENCHMARK