static bool watch(private_stream_t *this, int fd, watcher_event_t event)
{
bool keep = FALSE;
+ stream_cb_t cb;
switch (event)
{
case WATCHER_READ:
- keep = this->read_cb(this->read_data, &this->public);
- if (!keep)
+ cb = this->read_cb;
+ this->read_cb = NULL;
+ keep = cb(this->read_data, &this->public);
+ if (keep)
{
- this->read_cb = NULL;
+ this->read_cb = cb;
}
break;
case WATCHER_WRITE:
- keep = this->write_cb(this->write_data, &this->public);
- if (!keep)
+ cb = this->write_cb;
+ this->write_cb = NULL;
+ keep = cb(this->write_data, &this->public);
+ if (keep)
{
- this->write_cb = NULL;
+ this->write_cb = cb;
}
break;
case WATCHER_EXCEPT:
/**
* Callback function prototype, called when stream is ready.
*
- * It is not allowed to destroy the stream during the callback, this would
- * deadlock. Instead, return FALSE to destroy the stream. It is not allowed
- * to call on_read()/on_write() during this callback.
+ * It is allowed to destroy the stream during the callback, but only if it has
+ * no other active on_read()/on_write() callback and returns FALSE. It is not
+ * allowed to to call on_read()/on_write/() during the callback.
*
* As select() may return even if a read()/write() would actually block, it is
* recommended to use the non-blocking calls and handle return values
*
* @param data data passed during callback registration
* @param stream associated stream
- * @return FALSE to destroy the stream
+ * @return FALSE unregisters the invoked callback, TRUE keeps it
*/
typedef bool (*stream_cb_t)(void *data, stream_t *stream);