EBus.cpp 154 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812
  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_CASE(EBusTestAll, BusTypesAll);
  470. template <typename Bus>
  471. class EBusTestId
  472. : public EBusTestAll<Bus>
  473. {
  474. };
  475. TYPED_TEST_CASE(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_CASE(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_CASE_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