mirror of
https://github.com/fltk/fltk.git
synced 2026-06-05 08:06:35 +08:00
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:
@@ -831,7 +831,19 @@ public:
|
|||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** \defgroup fl_del_widget Safe widget deletion support functions
|
/** \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:
|
// Widget deletion:
|
||||||
static void delete_widget(Fl_Widget *w);
|
static void delete_widget(Fl_Widget *w);
|
||||||
|
|||||||
+69
-10
@@ -1467,10 +1467,9 @@ static Fl_Widget **dwidgets = 0;
|
|||||||
Use this method to delete a widget inside a callback function.
|
Use this method to delete a widget inside a callback function.
|
||||||
To avoid early deletion of widgets, this function
|
To avoid early deletion of widgets, this function
|
||||||
should be called toward the end of a callback and only after any call
|
should be called toward the end of a callback and only after any call
|
||||||
to the event loop (Fl:wait(), Fl::flush(),
|
to the event loop (Fl:wait(), Fl::flush(), fl_ask(), etc).
|
||||||
fl_ask(), etc).</p>
|
|
||||||
|
When deleting groups or windows, you must only delete the group or
|
||||||
<p>When deleting groups or windows, you must only delete the group or
|
|
||||||
window widget and not the individual child widgets.
|
window widget and not the individual child widgets.
|
||||||
*/
|
*/
|
||||||
void Fl::delete_widget(Fl_Widget *wi) {
|
void Fl::delete_widget(Fl_Widget *wi) {
|
||||||
@@ -1495,7 +1494,14 @@ void Fl::delete_widget(Fl_Widget *wi) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Deletes widgets previously scheduled for deletion.
|
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() {
|
void Fl::do_widget_deletion() {
|
||||||
if (!num_dwidgets) return;
|
if (!num_dwidgets) return;
|
||||||
@@ -1509,9 +1515,44 @@ void Fl::do_widget_deletion() {
|
|||||||
static Fl_Widget ***widget_watch = 0;
|
static Fl_Widget ***widget_watch = 0;
|
||||||
static int num_widget_watch = 0;
|
static int num_widget_watch = 0;
|
||||||
static int max_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)
|
void Fl::watch_widget_pointer(Fl_Widget *&w)
|
||||||
{
|
{
|
||||||
Fl_Widget **wp = &w;
|
Fl_Widget **wp = &w;
|
||||||
@@ -1532,7 +1573,14 @@ void Fl::watch_widget_pointer(Fl_Widget *&w)
|
|||||||
widget_watch[num_widget_watch++] = wp;
|
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)
|
void Fl::release_widget_pointer(Fl_Widget *&w)
|
||||||
{
|
{
|
||||||
Fl_Widget **wp = &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)
|
void Fl::clear_widget_pointer(Fl_Widget const *w)
|
||||||
{
|
{
|
||||||
if (w==0L) return;
|
if (w==0L) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user