-
-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deadlock when using helper.Duplicate function in the indicator package #243
Comments
Hi! Thank you for filling this issue. Yes, looking at your example code, by design, it will get into a deadlock, let me explain why, and how to get around that: Imagine helper.Duplicate() creates two copies of an input channel. It expects these copies to be used in a strict order:
If your code doesn't follow this order (e.g., trying to use outputs[1] before outputs[0]), it creates a "deadlock". From duplicate.go: for n := range input {
for _, output := range outputs {
output <- n
}
} In your example, One way to get around this is through the helper.Buffered(). It will allow you have a set a buffer for the channel, so that it won't block immediately. For example, in your case, if you use the helper.Buffered(), it will no longer get into a deadlock: package main
import (
"fmt"
"github.com/cinar/indicator/v2/helper"
)
func main() {
input := helper.SliceToChan([]float64{-10, 20, -4, -5})
outputs := helper.Duplicate(input, 2)
outputs[0] = helper.Buffered(outputs[0], 4)
outputs[1] = helper.Buffered(outputs[1], 4)
fmt.Println(helper.ChanToSlice(outputs[0]))
fmt.Println(helper.ChanToSlice(outputs[1]))
} I am very much interested in learning more about your use case. |
I noticed in your rsi_strategy.go code: // Report processes the provided asset snapshots and generates a report annotated with the recommended actions.
func (r *RsiStrategy) Report(c <-chan *asset.Snapshot) *helper.Report {
//
// snapshots[0] -> dates
// snapshots[1] -> Compute -> actions -> annotations
// snapshots[2] -> closings[0] -> close
// -> closings[1] -> Rsi.Compute -> rsi
//
snapshots := helper.Duplicate(c, 3)
dates := asset.SnapshotsAsDates(snapshots[0])
closings := helper.Duplicate(asset.SnapshotsAsClosings(snapshots[2]), 2)
rsi := helper.Shift(r.Rsi.Compute(closings[1]), r.Rsi.IdlePeriod(), 0)
actions, outcomes := strategy.ComputeWithOutcome(r, snapshots[1])
annotations := strategy.ActionsToAnnotations(actions)
outcomes = helper.MultiplyBy(outcomes, 100)
report := helper.NewReport(r.Name(), dates)
report.AddChart()
report.AddChart()
report.AddColumn(helper.NewNumericReportColumn("Close", closings[0]))
report.AddColumn(helper.NewNumericReportColumn("RSI", rsi), 1)
report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1)
report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 2)
return report
} I’m curious about why it’s possible to use snapshots without strictly following a sequential order here. Additionally, if I don’t know the exact buffer size needed, what would be a recommended approach to avoid potential deadlocks? |
Hello,
I encountered a deadlock issue when using the helper.Duplicate function in the indicator package. Here is the code I used to reproduce the issue:
Problem:
When running this code, it results in a deadlock. I expected the helper.Duplicate function to allow me to duplicate the input channel without causing a deadlock.
Environment:
Go version: go version go1.23.0 windows/amd64
Indicator version: github.com/cinar/indicator/v2 v2.1.7
Could you please take a look? I’d appreciate any guidance or suggestions to resolve this.
Thank you!
The text was updated successfully, but these errors were encountered: