Documentation ¶
Overview ¶
Package event provides a minimal select/poll/epoll/kqueue-based event loop for Go applications that require evented IO notifications. This is particularly useful for code that interfaces with asynchronous C libraries, which often assume an event loop is available.
This is an interface-only package, and has no dependencies of its own. Subpackage libevent provides a simple implementation which depends on the libevent C library (http://libevent.org).
There are a handful of other C libraries which also provide event loops, such as libev (http://software.schmorp.de/pkg/libev.html), libuv (https://github.com/joyent/libuv), CoreFoundation's CFRunLoop (https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFRunLoopRef/Reference/reference.html), glib's GMainLoop (https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html), and Qt's QSocketNotifier (http://qt-project.org/doc/qt-5.0/qtcore/qsocketnotifier.html). If you implement one of these backends, I strongly encourage you to make a pull request.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type IOFlags ¶
type IOFlags int16
IOFlags are used to describe file statuses. They may be bitwise-ORed if more than one status applies.
type IOSource ¶
type IOSource Source
An IOSource monitors an open file or socket's readable and/or writable status. IOSources are "level-triggered," meaning they will fire each time through the event loop for as long as the condition holds. (It also means that an infinite loop is likely to result if your event handler does not either change the file's state or remove itself from the loop.)
Example ¶
package main import ( "bitbucket.org/zobar/event" "bitbucket.org/zobar/event/libevent" "fmt" "os" "syscall" "time" ) func main() { wait := make(chan bool) // Get a reference to the shared libevent event loop. loop := libevent.MainLoop() hi := loop.IOSource(event.FD(syscall.Stdin), event.Read, func(event.IOSource, event.IOFlags) { // At this point, we have to read the bytes out of the file descriptor. // Otherwise the file descriptor will remain readable, and we will // continue to get notified. buf := make([]byte, 256) os.Stdin.Read(buf) fmt.Println("Hello, world!") }) // Events need to be explicitly added, or else they won't fire. hi.Add() // IOSources have no intrinsic timeout. If a timeout is desired, you must // create a separate TimerSource. bye := loop.TimerSource(2*time.Second, func(event.TimerSource) { fmt.Println("Goodbye.") close(wait) }) bye.Add() fmt.Println("Press enter quickly for a friendly message.") <-wait // Not normally necessary, but we need to clean up for the other examples. hi.Remove() bye.Remove() }
Output: Press enter quickly for a friendly message. Goodbye.
type Loop ¶
type Loop interface { // IOSource() creates a new IOSource for monitoring an open file's readable // and/or writable status. The event source is not active until Add() is // called on it. IOSource(fd FD, flags IOFlags, callback func(source IOSource, flags IOFlags)) IOSource // TimerSource() creates a new TimerSource for emitting events repeatedly // after a given timeout. The event source is not active until Add() is // called on it. TimerSource(timeout time.Duration, callback func(source TimerSource)) TimerSource }
Loop manages a set of IOSources and TimerSources. This is the main entry point to the event package. How you obtain a Loop depends on what type of code you're writing:
If you are writing a library, your best bet is to accept a Loop as a parameter to your top-level constructor. This will make your library more flexible, since it insulates your code from the implementation decisions of your users.
If you are writing an application, subpackage libevent makes a simple, shared event loop available through libevent.MainLoop(). Other implementations based on different libraries may eventually become available.
type Source ¶
type Source interface { // Add makes an event source active. Once an event source is active, it will // emit events until it is explicitly removed. Add() error // Remove is called to deactivate an event source. After an event source is // deactivated, it will no longer emit events. An event source can be added // again after it's been removed. Remove() error }
Source is a common interface implemented by all event sources.
type TimerSource ¶
type TimerSource Source
TimerSource is an event source which emits events repeatedly after a given timeout.
Example ¶
package main import ( "bitbucket.org/zobar/event" "bitbucket.org/zobar/event/libevent" "fmt" "time" ) func main() { wait := make(chan bool) // Get a reference to the shared libevent event loop. loop := libevent.MainLoop() // Events repeat until they are removed. tick := loop.TimerSource(500*time.Millisecond, func(event.TimerSource) { fmt.Printf("tick... ") }) // Events need to be explicitly added, or else they won't fire. tick.Add() boom := loop.TimerSource(2*time.Second, func(event.TimerSource) { fmt.Printf("BOOM!\n") close(wait) }) boom.Add() <-wait // Not normally necessary, but we need to clean up for the other examples. tick.Remove() boom.Remove() }
Output: tick... tick... tick... tick... BOOM!