object vs contextImage Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
郭學聰 Hsueh-Tsung KuoSun, 18 Aug 2019
ʕ◔ϖ◔ʔ
digraph M_N_threading {
nodesep=1.0 // increases the separation between nodes
node [color="red" shape=box]
edge [color="blue" style=dashed]
cpu1 [label="CPU core 1"]
cpu2 [label="CPU core 2"]
thread1 [label="thread M1" shape="oval"]
thread2 [label="thread M2" shape="oval"]
thread3 [label="thread M3" shape="oval"]
thread4 [label="thread M4" shape="oval"]
processor1 [label="logical processor P1" shape="oval"]
processor2 [label="logical processor P2" shape="oval"]
goroutine1 [label="goroutine G1" shape="oval"]
goroutine2 [label="goroutine G2" shape="oval"]
goroutine3 [label="goroutine G3" shape="oval"]
goroutine4 [label="goroutine G4" shape="oval"]
goroutine5 [label="goroutine G5" shape="oval"]
cpu1->thread1 [style=solid]
cpu2->thread2 [style=solid]
thread1->processor1 [style=solid]
thread2->processor2 [style=solid]
processor1->goroutine1 [style=solid]
processor1->goroutine2 [style=solid]
processor2->goroutine3 [style=solid]
processor2->goroutine4 [style=solid]
processor2->goroutine5 [style=solid]
}
how to trace process/thread/fiber?
Ruby
t = Thread.new { (1..5).each { puts('hello') sleep(1.0) } } t.terminate() t.join()
C#
Thread t = new Thread(new ThreadStart(object.Method)); t.Start(); t.Abort(); t.Join();
communicating sequential processes newbie:
manually assign channels for every goroutine!?
import "context" parentCtx := context.Background() childCtx, cancel := context.WithCancel(parentCtx) go function(ctx context.Context, param1 int, param2 string) error { for { select { case <-ctx.Done(): return ctx.Err() default: doSomething() } } }(childCtx, param1, param2) cancel()
digraph goroutine_tree {
nodesep=1.0 // increases the separation between nodes
node [color="green" shape=box]
edge [color="blue"]
goroutine1 [label="goroutine 1"]
goroutine2 [label="goroutine 2"]
goroutine3 [label="goroutine 3"]
goroutine4 [label="goroutine 4"]
goroutine5 [label="goroutine 5"]
goroutine6 [label="goroutine 6"]
goroutine7 [label="goroutine 7"]
goroutine1->goroutine2 [label = "context"]
goroutine2->goroutine3 [label = "context"]
goroutine2->goroutine4 [label = "context"]
goroutine2->goroutine5 [label = "context"]
goroutine5->goroutine6 [label = "context"]
goroutine5->goroutine7 [label = "context"]
}
digraph goroutine_tree {
nodesep=1.0 // increases the separation between nodes
node [color="gray" shape=box]
edge [color="gray" style=dashed]
goroutine1 [color="green" label="goroutine 1"]
goroutine2 [color="red" label="goroutine 2"]
goroutine3 [label="goroutine 3"]
goroutine4 [label="goroutine 4"]
goroutine5 [label="goroutine 5"]
goroutine6 [label="goroutine 6"]
goroutine7 [label="goroutine 7"]
goroutine1->goroutine2 [color="blue" label = "context" style=solid]
goroutine2->goroutine3 [label = "context"]
goroutine2->goroutine4 [label = "context"]
goroutine2->goroutine5 [label = "context"]
goroutine5->goroutine6 [label = "context"]
goroutine5->goroutine7 [label = "context"]
}
that is all?
// init parentCtx := context.Background() // map (goroutine scope variable) // store goroutine scope variable childCtx := context.WithValue(parentCtx, key, value) value, ok := childCtx.Value(key).(ValueType) // control // get cancel button childCtx, cancel := context.WithCancel(parentCtx) // get cancel button and set deadline childCtx, cancel := context.WithDeadline(parentCtx, deadline) // get cancel button and set timeout childCtx, cancel := context.WithTimeout(parentCtx, timeout)
every context.With*() string context as linked list
childCtx := context.WithValue(parentCtx, key, value) value, ok := childCtx.Value(key).(ValueType)
warning
The provided key must be comparable and should not be of type string or any other built-in type to avoid
collisions between packages using context. Users of WithValue should define their own types for keys. To avoid
allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported
context key variables' static type should be a pointer or interface.
warning
type contextKey int const ( contextKeySessionData = contextKey(1) ) contextWithSessionData := context.WithValue(r.Context(), contextKeySessionData, sessionData) sessionData, ok := r.Context().Value(contextKeySessionData).(*AuthSessionData)
// get cancel button childCtx, cancel := context.WithCancel(parentCtx)
// get cancel button and set deadline childCtx, cancel := context.WithDeadline(parentCtx, deadline)
// get cancel button and set timeout childCtx, cancel := context.WithTimeout(parentCtx, timeout)
import "sync" var wg sync.WaitGroup wg.Add(1) go function() { defer wg.Done() doSomething() }() wg.Wait()
note left of parent: wg.Add()
parent->child: go function()
note right of child: start
parent->child: cancel()
note right of child: case <-ctx.Done():
note right of child: stop
parent->child: call wg.Wait()
note right of child: wg.Done()
child->parent: wg.Wait() return
note
this is it
( >ω•)b
this is it
( O_o) ?
what about deeply nested goroutine?
( @д@) !
forget it
¯\_(ツ)_/¯
or more elegant way:
context =
(thread object) - (join) + (thread scope variable)
郭學聰 Hsueh-Tsung Kuo2019_08_18
Incoming requests to a server should create a Context,
and outgoing calls to servers should accept a Context.
elegant
func HandlerFunc(w http.ResponseWriter, r *http.Request) { ctx := r.Context() resource.Connect(ctx, param1, param2) ... }
Sdorica -mirage-
Rayark Careers | Make A Difference