xref: /haiku/headers/os/app/Looper.h (revision 14d02d22f66d08946519ad2b073be23fa78fc0c3)
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