mirror of
https://github.com/JoelBender/bacpypes
synced 2025-10-05 22:18:16 +08:00
110 lines
3.9 KiB
ReStructuredText
110 lines
3.9 KiB
ReStructuredText
.. BACpypes event module
|
|
|
|
.. module:: event
|
|
|
|
Event
|
|
=====
|
|
|
|
At the heart of :func:`core.run()` is a call to the **select** function of the
|
|
built in select module. That function is provided a list of file descriptors
|
|
and will exit when there is activity on one of them.
|
|
|
|
In a multi-threaded application, if the main thread is waiting for IO activity
|
|
then child threads need a mechanism to "wake up" the main thread. This may be
|
|
because the child thread has detected some timeout.
|
|
|
|
An instance of this class is used by the :class:`task.TaskManager` to wake up
|
|
the main thread when tasks are scheduled by child threads. If the child thread
|
|
is requesting "as soon as possible" execution of the task, then scheduling the
|
|
task wakes up the main thread, which causes it to be processed.
|
|
|
|
.. note::
|
|
This is not available on Windows platforms, which may suffer from a small
|
|
preformance hit. This can be mitigated somewhat by changing the **SPIN**
|
|
value in the **core** module.
|
|
|
|
Classes
|
|
-------
|
|
|
|
.. class:: WaitableEvent
|
|
|
|
The methods in this class provide the same interface as
|
|
**asyncore.file_dispatcher** and the ones that are typically used
|
|
in multi-threaded applications the way **Threading.Event** objects
|
|
are used.
|
|
|
|
These methods use an internal pipe to provide a "read" and "write" file
|
|
descriptors. There are no direct references to this pipe, only through
|
|
the file descriptors that are linked to it.
|
|
|
|
.. method:: __init__()
|
|
|
|
The internal file descriptors which are understood by the
|
|
**asyncore.loop** call in :func:`core.run()` are created by
|
|
calling **os.pipe()**, then initialization continues to
|
|
the usual **asyncore.file_dispatcher** initializer.
|
|
|
|
.. method:: __del__()
|
|
|
|
When an instance of this class is deleted, the file references to the
|
|
"read" and "write" sides of the pipe are closed. The OS will then
|
|
delete the pipe.
|
|
|
|
.. method:: readable()
|
|
|
|
This method returns ``True`` so it will always be included in the
|
|
list of file-like objects when waiting for IO activity.
|
|
|
|
.. method:: writable()
|
|
|
|
This method returns ``False`` becuase there is never any pending
|
|
write activity like there would be for a actual file or socket.
|
|
|
|
.. method:: handle_read()
|
|
|
|
This method performs no activity. If an instance of this event
|
|
is "set" then the only way to clear it is by calling :func:`clear()`
|
|
which will read the pending character out of the pipe.
|
|
|
|
.. method:: handle_write()
|
|
|
|
This function is never called because :func:`writable()` always
|
|
returns ``False``.
|
|
|
|
.. method:: handle_close()
|
|
|
|
This method is called when a close is requested, so this in
|
|
turn passes it to the **asyncore.file_dispatcher.close** function.
|
|
|
|
.. method:: wait(timeout=None)
|
|
|
|
:param float timeout: maximum time to wait for the event to be set
|
|
|
|
Similar to the way the **asyncore.loop** function will wait for
|
|
activity on a file descriptor, **select.select** is used by this
|
|
method to wait for some activity on the "read" side of its internal
|
|
pipe.
|
|
|
|
The :func:`set()` function will write to the "write" side of the pipe,
|
|
so the "read" side will have activity and the select function will
|
|
exit.
|
|
|
|
This function returns ``True`` if the "event" is "set".
|
|
|
|
.. method:: isSet()
|
|
|
|
This method calls :func:`wait()` with a zero timeout which essentially
|
|
probes the pipe to see if there is data waiting, which in turn implies
|
|
the "event" is "set".
|
|
|
|
.. method:: set()
|
|
|
|
Setting the event involves writing a single character to the internal
|
|
pipe, but only if there is no data in the pipe.
|
|
|
|
.. method:: clear()
|
|
|
|
Clearing the event involves reading the character that was written to
|
|
the intrenal pipe, provided one is there. If there is no data in the
|
|
pipe then the **os.read** function would stall the thread.
|