Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / event / core / export.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package core
6
7 import (
8         "context"
9         "sync/atomic"
10         "time"
11         "unsafe"
12
13         "golang.org/x/tools/internal/event/label"
14 )
15
16 // Exporter is a function that handles events.
17 // It may return a modified context and event.
18 type Exporter func(context.Context, Event, label.Map) context.Context
19
20 var (
21         exporter unsafe.Pointer
22 )
23
24 // SetExporter sets the global exporter function that handles all events.
25 // The exporter is called synchronously from the event call site, so it should
26 // return quickly so as not to hold up user code.
27 func SetExporter(e Exporter) {
28         p := unsafe.Pointer(&e)
29         if e == nil {
30                 // &e is always valid, and so p is always valid, but for the early abort
31                 // of ProcessEvent to be efficient it needs to make the nil check on the
32                 // pointer without having to dereference it, so we make the nil function
33                 // also a nil pointer
34                 p = nil
35         }
36         atomic.StorePointer(&exporter, p)
37 }
38
39 // deliver is called to deliver an event to the supplied exporter.
40 // it will fill in the time.
41 func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context {
42         // add the current time to the event
43         ev.at = time.Now()
44         // hand the event off to the current exporter
45         return exporter(ctx, ev, ev)
46 }
47
48 // Export is called to deliver an event to the global exporter if set.
49 func Export(ctx context.Context, ev Event) context.Context {
50         // get the global exporter and abort early if there is not one
51         exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
52         if exporterPtr == nil {
53                 return ctx
54         }
55         return deliver(ctx, *exporterPtr, ev)
56 }
57
58 // ExportPair is called to deliver a start event to the supplied exporter.
59 // It also returns a function that will deliver the end event to the same
60 // exporter.
61 // It will fill in the time.
62 func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) {
63         // get the global exporter and abort early if there is not one
64         exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
65         if exporterPtr == nil {
66                 return ctx, func() {}
67         }
68         ctx = deliver(ctx, *exporterPtr, begin)
69         return ctx, func() { deliver(ctx, *exporterPtr, end) }
70 }