is curl_global_init handled safely? is the library thread-safe?
is the library supposed to be thread safe? note that curl_global_init() is NOT thread-safe, and curl_easy_init is threadsafe ONLY IF curl_global_init() has already been executed. if you start several threads that all call curl_easy_init() at the same time, before curl_global_init has been executed, you may run into problems, how does this reflect on go-curl?
go-curl is not supposed to be thread safe. I haven't figured out How to restrict func calling order.
@andelf do something like
var curl_global_inited bool = false
func go_curl_global_init() {
var once sync.Once
onceBody := func() {
// call the real curl_global_init() here, and when done:
curl_global_inited = true
}
once.Do(onceBody)
for curl_global_inited != true {
// some thread is running curl_global_init, wait for it to finish.
// optimization notes, figure out if Go has built-in support for "wait until variable changes", and if 1 millisecond is a sane timeout?
time.Sleep(1 * time.Millisecond)
}
}
and have all applicable functions call go_curl_global_init(), then go-curl should be thread-safe. as for performance, you'll have the function call overhead, but the time.Sleep code should only ever be hit in situations where you would actually have race condition without it, and will only run at the very first curl function calls, if ever, so i don't think it is a significant performance hit.
also, i hope there's a way to make curl_global_inited a function-local static threads-shared variable, but i don't know. (ps, i'm not proficient with Go myself, only toyed with it)
You can also use init function to load a module, that should load it only once.
Example: https://github.com/umurkontaci/go-curl-transport/blob/master/transport/transport.go#L21-L23
@umurkontaci will that also help protect threads from calling curl_easy_init() before the thread calling curl_global_init() has completed the call?
Possibly, init is executed as the first thing when you import a module. But also it's quite possible to execute curl_easy_init before you import a specific module.
If you import the module in the application entrypoint you would probably be okay, but it's quite hacky way to do. It'd be better to encapsulate everything together.
actually, if you go with the sync.Once.Do method, you don't have to do the for curl_global_inited != true loop at all, because sync.Once.Do blocks other callers until it has executed completely. (according to guys on irc://irc.freenode.net/#go-nuts , anyway)