Documented module "Safe widget deletion support functions"
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6575 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
1849b8df5c
commit
8a45f9063c
14
FL/Fl.H
14
FL/Fl.H
@ -831,7 +831,19 @@ public:
|
||||
/** @} */
|
||||
|
||||
/** \defgroup fl_del_widget Safe widget deletion support functions
|
||||
fl multithreading support functions
|
||||
|
||||
These functions support deletion of widgets inside callbacks.
|
||||
|
||||
There are two groups of related methods:
|
||||
|
||||
-# scheduled widget deletion
|
||||
- Fl::delete_widget() schedules widgets for deletion
|
||||
- Fl::do_widget_deletion() deletes all scheduled widgets
|
||||
-# widget watch list ("smart pointers")
|
||||
- Fl::watch_widget_pointer() adds a widget pointer to the watch list
|
||||
- Fl::release_widget_pointer() removes a widget pointer from the watch list
|
||||
- Fl::clear_widget_pointer() clears a widget pointer \e in the watch list
|
||||
|
||||
@{ */
|
||||
// Widget deletion:
|
||||
static void delete_widget(Fl_Widget *w);
|
||||
|
79
src/Fl.cxx
79
src/Fl.cxx
@ -1467,10 +1467,9 @@ static Fl_Widget **dwidgets = 0;
|
||||
Use this method to delete a widget inside a callback function.
|
||||
To avoid early deletion of widgets, this function
|
||||
should be called toward the end of a callback and only after any call
|
||||
to the event loop (Fl:wait(), Fl::flush(),
|
||||
fl_ask(), etc).</p>
|
||||
|
||||
<p>When deleting groups or windows, you must only delete the group or
|
||||
to the event loop (Fl:wait(), Fl::flush(), fl_ask(), etc).
|
||||
|
||||
When deleting groups or windows, you must only delete the group or
|
||||
window widget and not the individual child widgets.
|
||||
*/
|
||||
void Fl::delete_widget(Fl_Widget *wi) {
|
||||
@ -1495,7 +1494,14 @@ void Fl::delete_widget(Fl_Widget *wi) {
|
||||
|
||||
/**
|
||||
Deletes widgets previously scheduled for deletion.
|
||||
See void Fl::delete_widget(Fl_Widget *wi)
|
||||
|
||||
This is for internal use only. You should never call this directly.
|
||||
|
||||
Fl::do_widget_deletion() is called from the FLTK event loop or whenever
|
||||
you call Fl::wait(). The previously scheduled widgets are deleted in the
|
||||
same order they were scheduled by calling Fl::delete_widget().
|
||||
|
||||
\see Fl::delete_widget(Fl_Widget *wi)
|
||||
*/
|
||||
void Fl::do_widget_deletion() {
|
||||
if (!num_dwidgets) return;
|
||||
@ -1509,9 +1515,44 @@ void Fl::do_widget_deletion() {
|
||||
static Fl_Widget ***widget_watch = 0;
|
||||
static int num_widget_watch = 0;
|
||||
static int max_widget_watch = 0;
|
||||
/** Adds a widget pointer to the watch list.
|
||||
\todo explain the role of the watch list,
|
||||
it may be related to invalid widget deletion crash fixes... */
|
||||
|
||||
/**
|
||||
Adds a widget pointer to the widget watch list.
|
||||
|
||||
This should be used, if it is possible that a widget might be deleted during
|
||||
a callback or similar function. The widget pointer must be added to the
|
||||
watch list before calling the callback. After the callback the widget
|
||||
pointer can be queried, if it is NULL. \e If it is NULL, then the widget has been
|
||||
deleted during the callback and must not be accessed anymore. If the widget
|
||||
pointer is \e not NULL, then the widget has not been deleted and can be accessed
|
||||
safely.
|
||||
|
||||
After accessing the widget, the widget pointer should be released from the
|
||||
watch list by calling Fl::release_widget_pointer().
|
||||
|
||||
Example for a button that is clicked (from its handle() method):
|
||||
\code
|
||||
Fl_Widget *wp = this; // save 'this' in a pointer variable
|
||||
Fl::watch_widget_pointer(wp); // add the pointer to the watch list
|
||||
set_changed(); // set the changed flag
|
||||
do_callback(); // call the callback
|
||||
if (!wp) { // the widget has been deleted
|
||||
|
||||
// DO NOT ACCESS THE DELETED WIDGET !
|
||||
|
||||
} else { // the widget still exists
|
||||
clear_changed(); // reset the changed flag
|
||||
}
|
||||
|
||||
Fl::release_widget_pointer(wp); // remove the pointer from the watch list
|
||||
\endcode
|
||||
|
||||
This works, because all widgets call Fl::clear_widget_pointer() in their
|
||||
destructors.
|
||||
|
||||
\see Fl::release_widget_pointer()
|
||||
\see Fl::clear_widget_pointer()
|
||||
*/
|
||||
void Fl::watch_widget_pointer(Fl_Widget *&w)
|
||||
{
|
||||
Fl_Widget **wp = &w;
|
||||
@ -1532,7 +1573,14 @@ void Fl::watch_widget_pointer(Fl_Widget *&w)
|
||||
widget_watch[num_widget_watch++] = wp;
|
||||
}
|
||||
|
||||
/** Releases a widget pointer to the watch list */
|
||||
/**
|
||||
Releases a widget pointer from the watch list.
|
||||
|
||||
This is used to remove a widget pointer that has been added to the watch list
|
||||
with Fl::watch_widget_pointer(), when it is not needed anymore.
|
||||
|
||||
\see Fl::watch_widget_pointer()
|
||||
*/
|
||||
void Fl::release_widget_pointer(Fl_Widget *&w)
|
||||
{
|
||||
Fl_Widget **wp = &w;
|
||||
@ -1544,7 +1592,18 @@ void Fl::release_widget_pointer(Fl_Widget *&w)
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Clears a widget pointer in the watch list */
|
||||
/**
|
||||
Clears a widget pointer \e in the watch list.
|
||||
|
||||
This is called when a widget is destroyed (by its destructor). You should never
|
||||
call this directly.
|
||||
|
||||
This method searches the widget watch list for pointers to the widget and clears
|
||||
all pointers that point to it. Widget pointers can be added to the widget
|
||||
watch list by calling Fl::watch_widget_pointer().
|
||||
|
||||
\see Fl::watch_widget_pointer()
|
||||
*/
|
||||
void Fl::clear_widget_pointer(Fl_Widget const *w)
|
||||
{
|
||||
if (w==0L) return;
|
||||
|
Loading…
Reference in New Issue
Block a user