PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llcallbacklist.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 256 lines | 170 code | 44 blank | 42 comment | 12 complexity | 92823f076c4c35e1b353c17fc25f031e MD5 | raw file
  1/** 
  2 * @file llcallbacklist.cpp
  3 * @brief A simple list of callback functions to call.
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llcallbacklist.h"
 30
 31// Library includes
 32#include "llerror.h"
 33
 34
 35//
 36// Globals
 37//
 38LLCallbackList gIdleCallbacks;
 39
 40//
 41// Member functions
 42//
 43
 44LLCallbackList::LLCallbackList()
 45{
 46	// nothing
 47}
 48
 49LLCallbackList::~LLCallbackList()
 50{
 51}
 52
 53
 54void LLCallbackList::addFunction( callback_t func, void *data)
 55{
 56	if (!func)
 57	{
 58		llerrs << "LLCallbackList::addFunction - function is NULL" << llendl;
 59		return;
 60	}
 61
 62	// only add one callback per func/data pair
 63	callback_pair_t t(func, data);
 64	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
 65	if (iter == mCallbackList.end())
 66	{
 67		mCallbackList.push_back(t);
 68	}
 69}
 70
 71
 72BOOL LLCallbackList::containsFunction( callback_t func, void *data)
 73{
 74	callback_pair_t t(func, data);
 75	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
 76	if (iter != mCallbackList.end())
 77	{
 78		return TRUE;
 79	}
 80	else
 81	{
 82		return FALSE;
 83	}
 84}
 85
 86
 87BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
 88{
 89	callback_pair_t t(func, data);
 90	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
 91	if (iter != mCallbackList.end())
 92	{
 93		mCallbackList.erase(iter);
 94		return TRUE;
 95	}
 96	else
 97	{
 98		return FALSE;
 99	}
100}
101
102
103void LLCallbackList::deleteAllFunctions()
104{
105	mCallbackList.clear();
106}
107
108
109void LLCallbackList::callFunctions()
110{
111	for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end();  )
112	{
113		callback_list_t::iterator curiter = iter++;
114		curiter->first(curiter->second);
115	}
116}
117
118// Shim class to allow arbitrary boost::bind
119// expressions to be run as one-time idle callbacks.
120class OnIdleCallbackOneTime
121{
122public:
123	OnIdleCallbackOneTime(nullary_func_t callable):
124		mCallable(callable)
125	{
126	}
127	static void onIdle(void *data)
128	{
129		gIdleCallbacks.deleteFunction(onIdle, data);
130		OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
131		self->call();
132		delete self;
133	}
134	void call()
135	{
136		mCallable();
137	}
138private:
139	nullary_func_t mCallable;
140};
141
142void doOnIdleOneTime(nullary_func_t callable)
143{
144	OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
145	gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
146}
147
148// Shim class to allow generic boost functions to be run as
149// recurring idle callbacks.  Callable should return true when done,
150// false to continue getting called.
151class OnIdleCallbackRepeating
152{
153public:
154	OnIdleCallbackRepeating(bool_func_t callable):
155		mCallable(callable)
156	{
157	}
158	// Will keep getting called until the callable returns true.
159	static void onIdle(void *data)
160	{
161		OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
162		bool done = self->call();
163		if (done)
164		{
165			gIdleCallbacks.deleteFunction(onIdle, data);
166			delete self;
167		}
168	}
169	bool call()
170	{
171		return mCallable();
172	}
173private:
174	bool_func_t mCallable;
175};
176
177void doOnIdleRepeating(bool_func_t callable)
178{
179	OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
180	gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
181}
182
183#ifdef _DEBUG
184
185void test1(void *data)
186{
187	S32 *s32_data = (S32 *)data;
188	llinfos << "testfunc1 " << *s32_data << llendl;
189}
190
191
192void test2(void *data)
193{
194	S32 *s32_data = (S32 *)data;
195	llinfos << "testfunc2 " << *s32_data << llendl;
196}
197
198
199void
200LLCallbackList::test()
201{
202	S32 a = 1;
203	S32 b = 2;
204	LLCallbackList *list = new LLCallbackList;
205
206	llinfos << "Testing LLCallbackList" << llendl;
207
208	if (!list->deleteFunction(NULL))
209	{
210		llinfos << "passed 1" << llendl;
211	}
212	else
213	{
214		llinfos << "error, removed function from empty list" << llendl;
215	}
216
217	// llinfos << "This should crash" << llendl;
218	// list->addFunction(NULL);
219
220	list->addFunction(&test1, &a);
221	list->addFunction(&test1, &a);
222
223	llinfos << "Expect: test1 1, test1 1" << llendl;
224	list->callFunctions();
225
226	list->addFunction(&test1, &b);
227	list->addFunction(&test2, &b);
228
229	llinfos << "Expect: test1 1, test1 1, test1 2, test2 2" << llendl;
230	list->callFunctions();
231
232	if (list->deleteFunction(&test1, &b))
233	{
234		llinfos << "passed 3" << llendl;
235	}
236	else
237	{
238		llinfos << "error removing function" << llendl;
239	}
240
241	llinfos << "Expect: test1 1, test1 1, test2 2" << llendl;
242	list->callFunctions();
243
244	list->deleteAllFunctions();
245
246	llinfos << "Expect nothing" << llendl;
247	list->callFunctions();
248
249	llinfos << "nothing :-)" << llendl;
250
251	delete list;
252
253	llinfos << "test complete" << llendl;
254}
255
256#endif  // _DEBUG