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