1*52a38012Sejakowatz //------------------------------------------------------------------------------ 2*52a38012Sejakowatz // Copyright (c) 2001-2002, OpenBeOS 3*52a38012Sejakowatz // 4*52a38012Sejakowatz // Permission is hereby granted, free of charge, to any person obtaining a 5*52a38012Sejakowatz // copy of this software and associated documentation files (the "Software"), 6*52a38012Sejakowatz // to deal in the Software without restriction, including without limitation 7*52a38012Sejakowatz // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*52a38012Sejakowatz // and/or sell copies of the Software, and to permit persons to whom the 9*52a38012Sejakowatz // Software is furnished to do so, subject to the following conditions: 10*52a38012Sejakowatz // 11*52a38012Sejakowatz // The above copyright notice and this permission notice shall be included in 12*52a38012Sejakowatz // all copies or substantial portions of the Software. 13*52a38012Sejakowatz // 14*52a38012Sejakowatz // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*52a38012Sejakowatz // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*52a38012Sejakowatz // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17*52a38012Sejakowatz // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18*52a38012Sejakowatz // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19*52a38012Sejakowatz // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20*52a38012Sejakowatz // DEALINGS IN THE SOFTWARE. 21*52a38012Sejakowatz // 22*52a38012Sejakowatz // File Name: Looper.h 23*52a38012Sejakowatz // Author(s): Erik Jaesler (erik@cgsoftware.com) 24*52a38012Sejakowatz // DarkWyrm (bpmagic@columbus.rr.com) 25*52a38012Sejakowatz // Description: BLooper class spawns a thread that runs a message loop. 26*52a38012Sejakowatz //------------------------------------------------------------------------------ 27*52a38012Sejakowatz 28*52a38012Sejakowatz #ifndef _LOOPER_H 29*52a38012Sejakowatz #define _LOOPER_H 30*52a38012Sejakowatz 31*52a38012Sejakowatz // Standard Includes ----------------------------------------------------------- 32*52a38012Sejakowatz 33*52a38012Sejakowatz // System Includes ------------------------------------------------------------- 34*52a38012Sejakowatz #include <BeBuild.h> 35*52a38012Sejakowatz #include <Handler.h> 36*52a38012Sejakowatz #include <List.h> 37*52a38012Sejakowatz #include <OS.h> 38*52a38012Sejakowatz 39*52a38012Sejakowatz // Project Includes ------------------------------------------------------------ 40*52a38012Sejakowatz 41*52a38012Sejakowatz // Local Includes -------------------------------------------------------------- 42*52a38012Sejakowatz 43*52a38012Sejakowatz // Local Defines --------------------------------------------------------------- 44*52a38012Sejakowatz 45*52a38012Sejakowatz // Globals --------------------------------------------------------------------- 46*52a38012Sejakowatz 47*52a38012Sejakowatz class BMessage; 48*52a38012Sejakowatz class BMessageQueue; 49*52a38012Sejakowatz struct _loop_data_; 50*52a38012Sejakowatz 51*52a38012Sejakowatz // Port (Message Queue) Capacity ----------------------------------------------- 52*52a38012Sejakowatz #define B_LOOPER_PORT_DEFAULT_CAPACITY 100 53*52a38012Sejakowatz 54*52a38012Sejakowatz 55*52a38012Sejakowatz // BLooper class --------------------------------------------------------------- 56*52a38012Sejakowatz class BLooper : public BHandler { 57*52a38012Sejakowatz public: 58*52a38012Sejakowatz BLooper(const char* name = NULL, 59*52a38012Sejakowatz int32 priority = B_NORMAL_PRIORITY, 60*52a38012Sejakowatz int32 port_capacity = B_LOOPER_PORT_DEFAULT_CAPACITY); 61*52a38012Sejakowatz virtual ~BLooper(); 62*52a38012Sejakowatz 63*52a38012Sejakowatz // Archiving 64*52a38012Sejakowatz BLooper(BMessage* data); 65*52a38012Sejakowatz static BArchivable* Instantiate(BMessage* data); 66*52a38012Sejakowatz virtual status_t Archive(BMessage* data, bool deep = true) const; 67*52a38012Sejakowatz 68*52a38012Sejakowatz // Message transmission 69*52a38012Sejakowatz status_t PostMessage(uint32 command); 70*52a38012Sejakowatz status_t PostMessage(BMessage* message); 71*52a38012Sejakowatz status_t PostMessage(uint32 command, 72*52a38012Sejakowatz BHandler* handler, 73*52a38012Sejakowatz BHandler* reply_to = NULL); 74*52a38012Sejakowatz status_t PostMessage(BMessage* message, 75*52a38012Sejakowatz BHandler* handler, 76*52a38012Sejakowatz BHandler* reply_to = NULL); 77*52a38012Sejakowatz 78*52a38012Sejakowatz virtual void DispatchMessage(BMessage* message, BHandler* handler); 79*52a38012Sejakowatz virtual void MessageReceived(BMessage* msg); 80*52a38012Sejakowatz BMessage* CurrentMessage() const; 81*52a38012Sejakowatz BMessage* DetachCurrentMessage(); 82*52a38012Sejakowatz BMessageQueue* MessageQueue() const; 83*52a38012Sejakowatz bool IsMessageWaiting() const; 84*52a38012Sejakowatz 85*52a38012Sejakowatz // Message handlers 86*52a38012Sejakowatz void AddHandler(BHandler* handler); 87*52a38012Sejakowatz bool RemoveHandler(BHandler* handler); 88*52a38012Sejakowatz int32 CountHandlers() const; 89*52a38012Sejakowatz BHandler* HandlerAt(int32 index) const; 90*52a38012Sejakowatz int32 IndexOf(BHandler* handler) const; 91*52a38012Sejakowatz 92*52a38012Sejakowatz BHandler* PreferredHandler() const; 93*52a38012Sejakowatz void SetPreferredHandler(BHandler* handler); 94*52a38012Sejakowatz 95*52a38012Sejakowatz // Loop control 96*52a38012Sejakowatz virtual thread_id Run(); 97*52a38012Sejakowatz virtual void Quit(); 98*52a38012Sejakowatz virtual bool QuitRequested(); 99*52a38012Sejakowatz bool Lock(); 100*52a38012Sejakowatz void Unlock(); 101*52a38012Sejakowatz bool IsLocked() const; 102*52a38012Sejakowatz status_t LockWithTimeout(bigtime_t timeout); 103*52a38012Sejakowatz thread_id Thread() const; 104*52a38012Sejakowatz team_id Team() const; 105*52a38012Sejakowatz static BLooper* LooperForThread(thread_id tid); 106*52a38012Sejakowatz 107*52a38012Sejakowatz // Loop debugging 108*52a38012Sejakowatz thread_id LockingThread() const; 109*52a38012Sejakowatz int32 CountLocks() const; 110*52a38012Sejakowatz int32 CountLockRequests() const; 111*52a38012Sejakowatz sem_id Sem() const; 112*52a38012Sejakowatz 113*52a38012Sejakowatz // Scripting 114*52a38012Sejakowatz virtual BHandler* ResolveSpecifier(BMessage* msg, 115*52a38012Sejakowatz int32 index, 116*52a38012Sejakowatz BMessage* specifier, 117*52a38012Sejakowatz int32 form, 118*52a38012Sejakowatz const char* property); 119*52a38012Sejakowatz virtual status_t GetSupportedSuites(BMessage* data); 120*52a38012Sejakowatz 121*52a38012Sejakowatz // Message filters (also see BHandler). 122*52a38012Sejakowatz virtual void AddCommonFilter(BMessageFilter* filter); 123*52a38012Sejakowatz virtual bool RemoveCommonFilter(BMessageFilter* filter); 124*52a38012Sejakowatz virtual void SetCommonFilterList(BList* filters); 125*52a38012Sejakowatz BList* CommonFilterList() const; 126*52a38012Sejakowatz 127*52a38012Sejakowatz // Private or reserved --------------------------------------------------------- 128*52a38012Sejakowatz virtual status_t Perform(perform_code d, void* arg); 129*52a38012Sejakowatz 130*52a38012Sejakowatz protected: 131*52a38012Sejakowatz // called from overridden task_looper 132*52a38012Sejakowatz BMessage* MessageFromPort(bigtime_t = B_INFINITE_TIMEOUT); 133*52a38012Sejakowatz 134*52a38012Sejakowatz private: 135*52a38012Sejakowatz typedef BHandler _inherited; 136*52a38012Sejakowatz friend class BWindow; 137*52a38012Sejakowatz friend class BApplication; 138*52a38012Sejakowatz friend class BMessenger; 139*52a38012Sejakowatz friend class BView; 140*52a38012Sejakowatz friend class BHandler; 141*52a38012Sejakowatz friend port_id _get_looper_port_(const BLooper* ); 142*52a38012Sejakowatz friend status_t _safe_get_server_token_(const BLooper* , int32* ); 143*52a38012Sejakowatz friend team_id _find_cur_team_id_(); 144*52a38012Sejakowatz 145*52a38012Sejakowatz virtual void _ReservedLooper1(); 146*52a38012Sejakowatz virtual void _ReservedLooper2(); 147*52a38012Sejakowatz virtual void _ReservedLooper3(); 148*52a38012Sejakowatz virtual void _ReservedLooper4(); 149*52a38012Sejakowatz virtual void _ReservedLooper5(); 150*52a38012Sejakowatz virtual void _ReservedLooper6(); 151*52a38012Sejakowatz 152*52a38012Sejakowatz BLooper(const BLooper&); 153*52a38012Sejakowatz BLooper& operator=(const BLooper&); 154*52a38012Sejakowatz 155*52a38012Sejakowatz BLooper(int32 priority, port_id port, const char* name); 156*52a38012Sejakowatz 157*52a38012Sejakowatz status_t _PostMessage(BMessage* msg, 158*52a38012Sejakowatz BHandler* handler, 159*52a38012Sejakowatz BHandler* reply_to); 160*52a38012Sejakowatz 161*52a38012Sejakowatz static status_t _Lock(BLooper* loop, 162*52a38012Sejakowatz port_id port, 163*52a38012Sejakowatz bigtime_t timeout); 164*52a38012Sejakowatz static status_t _LockComplete(BLooper* loop, 165*52a38012Sejakowatz int32 old, 166*52a38012Sejakowatz thread_id this_tid, 167*52a38012Sejakowatz sem_id sem, 168*52a38012Sejakowatz bigtime_t timeout); 169*52a38012Sejakowatz void InitData(); 170*52a38012Sejakowatz void InitData(const char* name, int32 prio, int32 capacity); 171*52a38012Sejakowatz void AddMessage(BMessage* msg); 172*52a38012Sejakowatz void _AddMessagePriv(BMessage* msg); 173*52a38012Sejakowatz static status_t _task0_(void* arg); 174*52a38012Sejakowatz 175*52a38012Sejakowatz void* ReadRawFromPort(int32* code, 176*52a38012Sejakowatz bigtime_t tout = B_INFINITE_TIMEOUT); 177*52a38012Sejakowatz BMessage* ReadMessageFromPort(bigtime_t tout = B_INFINITE_TIMEOUT); 178*52a38012Sejakowatz virtual BMessage* ConvertToMessage(void* raw, int32 code); 179*52a38012Sejakowatz virtual void task_looper(); 180*52a38012Sejakowatz void do_quit_requested(BMessage* msg); 181*52a38012Sejakowatz bool AssertLocked() const; 182*52a38012Sejakowatz BHandler* top_level_filter(BMessage* msg, BHandler* t); 183*52a38012Sejakowatz BHandler* handler_only_filter(BMessage* msg, BHandler* t); 184*52a38012Sejakowatz BHandler* apply_filters( BList* list, 185*52a38012Sejakowatz BMessage* msg, 186*52a38012Sejakowatz BHandler* target); 187*52a38012Sejakowatz void check_lock(); 188*52a38012Sejakowatz BHandler* resolve_specifier(BHandler* target, BMessage* msg); 189*52a38012Sejakowatz void UnlockFully(); 190*52a38012Sejakowatz 191*52a38012Sejakowatz static uint32 sLooperID; 192*52a38012Sejakowatz static uint32 sLooperListSize; 193*52a38012Sejakowatz static uint32 sLooperCount; 194*52a38012Sejakowatz static _loop_data_* sLooperList; 195*52a38012Sejakowatz static BLocker sLooperListLock; 196*52a38012Sejakowatz static team_id sTeamID; 197*52a38012Sejakowatz 198*52a38012Sejakowatz static void AddLooper(BLooper* l); 199*52a38012Sejakowatz static bool IsLooperValid(const BLooper* l); 200*52a38012Sejakowatz static void RemoveLooper(BLooper* l); 201*52a38012Sejakowatz static void GetLooperList(BList* list); 202*52a38012Sejakowatz static BLooper* LooperForName(const char* name); 203*52a38012Sejakowatz static BLooper* LooperForPort(port_id port); 204*52a38012Sejakowatz 205*52a38012Sejakowatz uint32 fLooperID; 206*52a38012Sejakowatz BMessageQueue* fQueue; 207*52a38012Sejakowatz BMessage* fLastMessage; 208*52a38012Sejakowatz port_id fMsgPort; 209*52a38012Sejakowatz long fAtomicCount; 210*52a38012Sejakowatz sem_id fLockSem; 211*52a38012Sejakowatz long fOwnerCount; 212*52a38012Sejakowatz thread_id fOwner; 213*52a38012Sejakowatz thread_id fTaskID; 214*52a38012Sejakowatz uint32 _unused1; 215*52a38012Sejakowatz int32 fInitPriority; 216*52a38012Sejakowatz BHandler* fPreferred; 217*52a38012Sejakowatz BList fHandlers; 218*52a38012Sejakowatz BList* fCommonFilters; 219*52a38012Sejakowatz bool fTerminating; 220*52a38012Sejakowatz bool fRunCalled; 221*52a38012Sejakowatz thread_id fCachedPid; 222*52a38012Sejakowatz size_t fCachedStack; 223*52a38012Sejakowatz void* fMsgBuffer; 224*52a38012Sejakowatz size_t fMsgBufferSize; 225*52a38012Sejakowatz uint32 _reserved[6]; 226*52a38012Sejakowatz }; 227*52a38012Sejakowatz //------------------------------------------------------------------------------ 228*52a38012Sejakowatz 229*52a38012Sejakowatz #endif // _LOOPER_H 230*52a38012Sejakowatz 231*52a38012Sejakowatz /* 232*52a38012Sejakowatz * $Log $ 233*52a38012Sejakowatz * 234*52a38012Sejakowatz * $Id $ 235*52a38012Sejakowatz * 236*52a38012Sejakowatz */ 237*52a38012Sejakowatz 238