152a38012Sejakowatz //------------------------------------------------------------------------------ 252a38012Sejakowatz // Copyright (c) 2001-2002, OpenBeOS 352a38012Sejakowatz // 452a38012Sejakowatz // Permission is hereby granted, free of charge, to any person obtaining a 552a38012Sejakowatz // copy of this software and associated documentation files (the "Software"), 652a38012Sejakowatz // to deal in the Software without restriction, including without limitation 752a38012Sejakowatz // the rights to use, copy, modify, merge, publish, distribute, sublicense, 852a38012Sejakowatz // and/or sell copies of the Software, and to permit persons to whom the 952a38012Sejakowatz // Software is furnished to do so, subject to the following conditions: 1052a38012Sejakowatz // 1152a38012Sejakowatz // The above copyright notice and this permission notice shall be included in 1252a38012Sejakowatz // all copies or substantial portions of the Software. 1352a38012Sejakowatz // 1452a38012Sejakowatz // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1552a38012Sejakowatz // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1652a38012Sejakowatz // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1752a38012Sejakowatz // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1852a38012Sejakowatz // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1952a38012Sejakowatz // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2052a38012Sejakowatz // DEALINGS IN THE SOFTWARE. 2152a38012Sejakowatz // 2252a38012Sejakowatz // File Name: Looper.h 2352a38012Sejakowatz // Author(s): Erik Jaesler (erik@cgsoftware.com) 2452a38012Sejakowatz // DarkWyrm (bpmagic@columbus.rr.com) 2552a38012Sejakowatz // Description: BLooper class spawns a thread that runs a message loop. 2652a38012Sejakowatz //------------------------------------------------------------------------------ 2752a38012Sejakowatz 2852a38012Sejakowatz #ifndef _LOOPER_H 2952a38012Sejakowatz #define _LOOPER_H 3052a38012Sejakowatz 3152a38012Sejakowatz // Standard Includes ----------------------------------------------------------- 3252a38012Sejakowatz 3352a38012Sejakowatz // System Includes ------------------------------------------------------------- 3452a38012Sejakowatz #include <BeBuild.h> 3552a38012Sejakowatz #include <Handler.h> 3652a38012Sejakowatz #include <List.h> 3752a38012Sejakowatz #include <OS.h> 3852a38012Sejakowatz 3952a38012Sejakowatz // Project Includes ------------------------------------------------------------ 4052a38012Sejakowatz 4152a38012Sejakowatz // Local Includes -------------------------------------------------------------- 4252a38012Sejakowatz 4352a38012Sejakowatz // Local Defines --------------------------------------------------------------- 4452a38012Sejakowatz 4552a38012Sejakowatz // Globals --------------------------------------------------------------------- 4652a38012Sejakowatz 4752a38012Sejakowatz class BMessage; 4852a38012Sejakowatz class BMessageQueue; 49abb57933Sejakowatz namespace BPrivate { 50abb57933Sejakowatz class BLooperList; 51abb57933Sejakowatz } 5252a38012Sejakowatz struct _loop_data_; 5352a38012Sejakowatz 5452a38012Sejakowatz // Port (Message Queue) Capacity ----------------------------------------------- 5552a38012Sejakowatz #define B_LOOPER_PORT_DEFAULT_CAPACITY 100 5652a38012Sejakowatz 5752a38012Sejakowatz 5852a38012Sejakowatz // BLooper class --------------------------------------------------------------- 5952a38012Sejakowatz class BLooper : public BHandler { 6052a38012Sejakowatz public: 6152a38012Sejakowatz BLooper(const char* name = NULL, 6252a38012Sejakowatz int32 priority = B_NORMAL_PRIORITY, 6352a38012Sejakowatz int32 port_capacity = B_LOOPER_PORT_DEFAULT_CAPACITY); 6452a38012Sejakowatz virtual ~BLooper(); 6552a38012Sejakowatz 6652a38012Sejakowatz // Archiving 6752a38012Sejakowatz BLooper(BMessage* data); 6852a38012Sejakowatz static BArchivable* Instantiate(BMessage* data); 6952a38012Sejakowatz virtual status_t Archive(BMessage* data, bool deep = true) const; 7052a38012Sejakowatz 7152a38012Sejakowatz // Message transmission 7252a38012Sejakowatz status_t PostMessage(uint32 command); 7352a38012Sejakowatz status_t PostMessage(BMessage* message); 7452a38012Sejakowatz status_t PostMessage(uint32 command, 7552a38012Sejakowatz BHandler* handler, 7652a38012Sejakowatz BHandler* reply_to = NULL); 7752a38012Sejakowatz status_t PostMessage(BMessage* message, 7852a38012Sejakowatz BHandler* handler, 7952a38012Sejakowatz BHandler* reply_to = NULL); 8052a38012Sejakowatz 8152a38012Sejakowatz virtual void DispatchMessage(BMessage* message, BHandler* handler); 8252a38012Sejakowatz virtual void MessageReceived(BMessage* msg); 8352a38012Sejakowatz BMessage* CurrentMessage() const; 8452a38012Sejakowatz BMessage* DetachCurrentMessage(); 8552a38012Sejakowatz BMessageQueue* MessageQueue() const; 8652a38012Sejakowatz bool IsMessageWaiting() const; 8752a38012Sejakowatz 8852a38012Sejakowatz // Message handlers 8952a38012Sejakowatz void AddHandler(BHandler* handler); 9052a38012Sejakowatz bool RemoveHandler(BHandler* handler); 9152a38012Sejakowatz int32 CountHandlers() const; 9252a38012Sejakowatz BHandler* HandlerAt(int32 index) const; 9352a38012Sejakowatz int32 IndexOf(BHandler* handler) const; 9452a38012Sejakowatz 9552a38012Sejakowatz BHandler* PreferredHandler() const; 9652a38012Sejakowatz void SetPreferredHandler(BHandler* handler); 9752a38012Sejakowatz 9852a38012Sejakowatz // Loop control 9952a38012Sejakowatz virtual thread_id Run(); 10052a38012Sejakowatz virtual void Quit(); 10152a38012Sejakowatz virtual bool QuitRequested(); 10252a38012Sejakowatz bool Lock(); 10352a38012Sejakowatz void Unlock(); 10452a38012Sejakowatz bool IsLocked() const; 10552a38012Sejakowatz status_t LockWithTimeout(bigtime_t timeout); 10652a38012Sejakowatz thread_id Thread() const; 10752a38012Sejakowatz team_id Team() const; 10852a38012Sejakowatz static BLooper* LooperForThread(thread_id tid); 10952a38012Sejakowatz 11052a38012Sejakowatz // Loop debugging 11152a38012Sejakowatz thread_id LockingThread() const; 11252a38012Sejakowatz int32 CountLocks() const; 11352a38012Sejakowatz int32 CountLockRequests() const; 11452a38012Sejakowatz sem_id Sem() const; 11552a38012Sejakowatz 11652a38012Sejakowatz // Scripting 11752a38012Sejakowatz virtual BHandler* ResolveSpecifier(BMessage* msg, 11852a38012Sejakowatz int32 index, 11952a38012Sejakowatz BMessage* specifier, 12052a38012Sejakowatz int32 form, 12152a38012Sejakowatz const char* property); 12252a38012Sejakowatz virtual status_t GetSupportedSuites(BMessage* data); 12352a38012Sejakowatz 12452a38012Sejakowatz // Message filters (also see BHandler). 12552a38012Sejakowatz virtual void AddCommonFilter(BMessageFilter* filter); 12652a38012Sejakowatz virtual bool RemoveCommonFilter(BMessageFilter* filter); 12752a38012Sejakowatz virtual void SetCommonFilterList(BList* filters); 12852a38012Sejakowatz BList* CommonFilterList() const; 12952a38012Sejakowatz 13052a38012Sejakowatz // Private or reserved --------------------------------------------------------- 13152a38012Sejakowatz virtual status_t Perform(perform_code d, void* arg); 13252a38012Sejakowatz 13352a38012Sejakowatz protected: 13452a38012Sejakowatz // called from overridden task_looper 13552a38012Sejakowatz BMessage* MessageFromPort(bigtime_t = B_INFINITE_TIMEOUT); 13652a38012Sejakowatz 13752a38012Sejakowatz private: 13852a38012Sejakowatz typedef BHandler _inherited; 13952a38012Sejakowatz friend class BWindow; 14052a38012Sejakowatz friend class BApplication; 14152a38012Sejakowatz friend class BMessenger; 14252a38012Sejakowatz friend class BView; 14352a38012Sejakowatz friend class BHandler; 144abb57933Sejakowatz friend class BPrivate::BLooperList; 14552a38012Sejakowatz friend port_id _get_looper_port_(const BLooper* ); 14652a38012Sejakowatz friend status_t _safe_get_server_token_(const BLooper* , int32* ); 14752a38012Sejakowatz friend team_id _find_cur_team_id_(); 14852a38012Sejakowatz 14952a38012Sejakowatz virtual void _ReservedLooper1(); 15052a38012Sejakowatz virtual void _ReservedLooper2(); 15152a38012Sejakowatz virtual void _ReservedLooper3(); 15252a38012Sejakowatz virtual void _ReservedLooper4(); 15352a38012Sejakowatz virtual void _ReservedLooper5(); 15452a38012Sejakowatz virtual void _ReservedLooper6(); 15552a38012Sejakowatz 15652a38012Sejakowatz BLooper(const BLooper&); 15752a38012Sejakowatz BLooper& operator=(const BLooper&); 15852a38012Sejakowatz 15952a38012Sejakowatz BLooper(int32 priority, port_id port, const char* name); 16052a38012Sejakowatz 16152a38012Sejakowatz status_t _PostMessage(BMessage* msg, 16252a38012Sejakowatz BHandler* handler, 16352a38012Sejakowatz BHandler* reply_to); 16452a38012Sejakowatz 16552a38012Sejakowatz static status_t _Lock(BLooper* loop, 16652a38012Sejakowatz port_id port, 16752a38012Sejakowatz bigtime_t timeout); 16852a38012Sejakowatz static status_t _LockComplete(BLooper* loop, 16952a38012Sejakowatz int32 old, 17052a38012Sejakowatz thread_id this_tid, 17152a38012Sejakowatz sem_id sem, 17252a38012Sejakowatz bigtime_t timeout); 17352a38012Sejakowatz void InitData(); 17452a38012Sejakowatz void InitData(const char* name, int32 prio, int32 capacity); 17552a38012Sejakowatz void AddMessage(BMessage* msg); 17652a38012Sejakowatz void _AddMessagePriv(BMessage* msg); 17752a38012Sejakowatz static status_t _task0_(void* arg); 17852a38012Sejakowatz 17952a38012Sejakowatz void* ReadRawFromPort(int32* code, 18052a38012Sejakowatz bigtime_t tout = B_INFINITE_TIMEOUT); 18152a38012Sejakowatz BMessage* ReadMessageFromPort(bigtime_t tout = B_INFINITE_TIMEOUT); 18252a38012Sejakowatz virtual BMessage* ConvertToMessage(void* raw, int32 code); 18352a38012Sejakowatz virtual void task_looper(); 184*14d02d22SAxel Dörfler void _QuitRequested(BMessage* msg); 18552a38012Sejakowatz bool AssertLocked() const; 186*14d02d22SAxel Dörfler BHandler* _TopLevelFilter(BMessage* msg, BHandler* target); 187*14d02d22SAxel Dörfler BHandler* _HandlerFilter(BMessage* msg, BHandler* target); 188*14d02d22SAxel Dörfler BHandler* _ApplyFilters(BList* list, BMessage* msg, 18952a38012Sejakowatz BHandler* target); 19052a38012Sejakowatz void check_lock(); 19152a38012Sejakowatz BHandler* resolve_specifier(BHandler* target, BMessage* msg); 19252a38012Sejakowatz void UnlockFully(); 19352a38012Sejakowatz 19452a38012Sejakowatz static uint32 sLooperID; 19552a38012Sejakowatz static team_id sTeamID; 19652a38012Sejakowatz 197752c4971Sejakowatz // DEPRECATED 19852a38012Sejakowatz static void AddLooper(BLooper* l); 19952a38012Sejakowatz static bool IsLooperValid(const BLooper* l); 20052a38012Sejakowatz static void RemoveLooper(BLooper* l); 20152a38012Sejakowatz static void GetLooperList(BList* list); 20252a38012Sejakowatz static BLooper* LooperForName(const char* name); 20352a38012Sejakowatz static BLooper* LooperForPort(port_id port); 20452a38012Sejakowatz 20552a38012Sejakowatz uint32 fLooperID; 20652a38012Sejakowatz BMessageQueue* fQueue; 20752a38012Sejakowatz BMessage* fLastMessage; 20852a38012Sejakowatz port_id fMsgPort; 20952a38012Sejakowatz long fAtomicCount; 21052a38012Sejakowatz sem_id fLockSem; 21152a38012Sejakowatz long fOwnerCount; 21252a38012Sejakowatz thread_id fOwner; 21352a38012Sejakowatz thread_id fTaskID; 21452a38012Sejakowatz uint32 _unused1; 21552a38012Sejakowatz int32 fInitPriority; 21652a38012Sejakowatz BHandler* fPreferred; 21752a38012Sejakowatz BList fHandlers; 21852a38012Sejakowatz BList* fCommonFilters; 21952a38012Sejakowatz bool fTerminating; 22052a38012Sejakowatz bool fRunCalled; 22152a38012Sejakowatz thread_id fCachedPid; 22252a38012Sejakowatz size_t fCachedStack; 22352a38012Sejakowatz void* fMsgBuffer; 22452a38012Sejakowatz size_t fMsgBufferSize; 22552a38012Sejakowatz uint32 _reserved[6]; 22652a38012Sejakowatz }; 22752a38012Sejakowatz //------------------------------------------------------------------------------ 22852a38012Sejakowatz 22952a38012Sejakowatz #endif // _LOOPER_H 23052a38012Sejakowatz 23152a38012Sejakowatz /* 23252a38012Sejakowatz * $Log $ 23352a38012Sejakowatz * 23452a38012Sejakowatz * $Id $ 23552a38012Sejakowatz * 23652a38012Sejakowatz */ 23752a38012Sejakowatz 238